Port access
Getting a port from a task is as easy as
port_object = my_task.port_name
The returned port object is either an {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::InputPort”}} or an {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::OutputPort”}}, based on the port type.
Creating connections
A connection is always created from an output port to an input port:
output_port.connect_to input_port
By default, the created connection is a data connection. To change that, one can use the :type option
output_port.connect_to input_port, :type => :buffer, :size => 10
Both ports must have the same type, otherwise a ConnectionFailed exception is raised.
Be reminded, that an input port can be part of multiple connections, i.e. multiple output ports can be connected to the same input port.
Disconnecting
There are different ways to disconnect ports
- one can specify a specific connection to remove:
output_port.disconnect_from input_port
- one can completely disconnect an input port
input_port.disconnect_all
- one can completely disconnect an output port
output_port.disconnect_all
Note that it is fine to use the first method even though the process hosting the input port is dead (e.g. has crashed or cannot be contacted). If it is the output port that is dead, then one should use the second method.
Reading outputs or writing inputs
One can read outputs and write inputs from the Ruby scripts. To achieve this, one gets a {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::OutputReader”}} or a {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::InputWriter”}} object (respectively) with:
writer = input_port.writer
reader = output_port.reader
By default, these port access objects will use a data policy for their connection to the port. To specify a buffer policy, simply do
writer = input_port.writer :type => :buffer, :size => 10
reader = output_port.reader :type => :buffer, :size => 10
Then, the data can be read with
sample = reader.read
the returned value will be nil if there is no data available, and the corresponding Typelib::Type object otherwise. It always return a sample if the connection has been written at least once.
To get only new samples (i.e. samples that you never read already), do
sample = reader.read_new
The returned object allows to manipulate the C++ data structure as if it was a normal Ruby object. For instance, a data sample looking like
struct LaserReadings
{
std::string name;
base::Time time;
std::vector<double> readings;
};
One can do
sample.name # returns a Ruby string
sample.time # returns a Typelib object that has .seconds and .microseconds methods
sample.readings # returns an Enumerable of floating-point values
and written with
sample = writer.new_sample
sample.name = "MyReading"
sample.time.seconds = Time.now.tv_sec
sample.time.microseconds = Time.now.tv_usec
writer.write(sample)