YarpBottleGenerator
 All Classes Files Functions Variables Pages
yarp-bottle-generator

Although this repository is integrated within VisLab's projects, it holds the result of my (Miguel Aragão) master thesis.

Brief description

The main goal of the yarp-bottle-generator is for it to be able to generate code that gets data from several sources (YARP ports or ROS topics) and builds a bottle to be sent to some specific ROS topic or YARP port.

The final user will only have to customize a configuration file according to his needs.

For now there are 3 main structures that the user can customize: the multiplexers (i.e. hubs), the converters and the output builder (described in a ROS message style). Please read the documentation on how to customize your own configuration file in order to understand how they work and what you can achieve with them.

Dependencies

The repository has two major dependencies:

The code was written in C++ so any environment able to compile it (and compatible with the dependencies) should be fine.

Download

Open a terminal:

cd /path/to/destination/folder
git clone https://github.com/vislab-tecnico-lisboa/yarp-bottle-generator.git

Set the environment variable

In order to run the generator you'll need to export the $BOTTLE_GENERATOR_DIR. Add the export to a script or execute it each time you want to run the generator:

export BOTTLE_GENERATOR_DIR = /path/to/destination/folder/yarp-bottle-generator

Compile the generator

Open a terminal:

cd $BOTTLE_GENERATOR_DIR
mkdir build
cd build
cmake ..
make

Optionally you can copy the executable to your bin folder (and be able to run it from everywhere):

sudo make install

Generate a node with the default configuration file

Open a terminal:

yarpBottleGenerator

in order to see the command arguments:

args:
[0]: configuration file name
[1]: generated code file name

In case you didn't run sudo make install you might need to run the last command from your build folder:

cd $BOTTLE_GENERATOR_DIR/build
./yarpBottleGenerator <configuration file> <filename_generated_code.cpp>

The configuration file must be located in the app folder of the repository, and the generated code will be located in a folder inside the results folder of the repository. The filename of the generated code should have the .cpp extension.

Compile the generated node

Open a terminal:

cd $BOTTLE_GENERATOR_DIR/results/<filename_generated_code>
mkdir build
cd build
cmake ..
make

That's it! In case you didn't change the generated code yourself this should compile with no errors. Please open an issue in case you are having problems compiling unchanged generated code.

Feel free to edit the code to add some extra functionality at your own risk. Please open an issue if you think those changes should be automated to other users. I'll be available to help you with any doubts and problems.

Run the generated node

Don't forget this is a YARP executable so you'll need to have a yarpserver running in order to run the code and if you are interacting with ROS, the runtime converter yarpidl_rosmsg must be running as well.

Open a terminal:

yarpserver
yarpidl_rosmsg

Execute your existing YARP modules and/or ROS nodes, and the code generated by yarp-bottle-generator.

Customize your own configuration file

The interesting stuff starts now!

I recommend you to read the previous paragraphs to understand how to setup the envinronment and run the code in case you didn't do it already.

I'll split this documentation in 3 parts: general, multiplexers and message builder. In the current state of the development YOU'LL HAVE TO CONFIGURE ALL THE 4 PARTS in order to correctly customize your own configuration file.

In the folder $BOTTLE_GENERATOR_DIR/app, create a text file that you have to edit in order to run the generator with your own configuration.

General

Sections

This part has 1 section: [general].

Section [general]

It has 3 variables: output_name, to_ros and num_mux.

output_name : The name of the output topic/port. The bottle will be sent to this topic/port.

to_ros : This variable expects true or false, true when the module is supposed to send a message to a ROS topic and false when the output is a YARP port.

from_ros_topics : This flag serves to decide if the input entities are ports or topics. Currently the supported data types are the ones translated by the run-time converter yarpidl_rosmsg.

num_mux : The number of multiplexers (i.e. Hubs) you want to create.

Example

[general]
output_name = /topic_name
to_ros = true
num_mux = 3

Multiplexers (i.e. Hubs)

Sections

This part has 0 or more sections: [mux1]...[muxn].

The generator expects an equal number of multiplexers and converters so the variables to configure the converter are in each multiplexer section (the last 2 variables are the ones that configure the converter).

Sections [mux1]...[muxn]

They have 4 variables: num_ports, ports, function and verbose.

num_ports : The number of input ports/topics on the multiplexer.

ports : The name of all the input ports/topics. Each input name should be separated by a comma (in the end the number of commas should be equal to num_ports - 1). All white spaces will be excluded from the input names.

function : The name of one of the available functions (list of functions above). Each function expects specific arguments so be careful to specify a function compatible with the data contained on the multiplexer.

List of functions:

verbose : This variable expects two possible values: true or false. In case you set it to true, the converter will print all the information about the data that passes through it. Not all the functions will have stuff to print but there is no problem setting this variable to true in those cases.

Example

[mux1]
num_ports = 4
ports = we , are , 4 , ports
function = none
verbose = false

[mux2]
num_ports = 2
ports = just , 2
function = none_double
verbose = true

[mux3]
num_ports = 1
# Yes! Altough it's a multiplexer it can accept only 1 port/topic as the input...
ports = dummy_mux_port
function = deg_to_rad
verbose = false

Message builder

Sections

This part has 1 or more sections: [message], [unique_name_1]...[unique_name_n].

It differs from the other parts because although sections might have completely different names the variables will have the same functionality and syntax on all of them. The only mandatory section is the message and the other ones can be named at your taste although it has to be an unique name.

Sections [message] and [unique_name_1] to [unique_name_n]

In case you have set the output as a YARP port you can organize your message the way you want but in case you set the output as a ROS topic each of this sections should match a ROS message. Why more than one section? Because ROS messages can have variables of non-primitive types. A non-primitive type will be represented by another section. Too confusing? Please check the instructions above.

They have 1 or more variables: num_fields and 1_stuff...n_stuff.

The fields should be organized ON THE SAME ORDER AS THEY ARE ON THE ROS MESSAGE!

num_fields : The number of fields of the ROS message. Both primitive and non-primitive variables should count as 1 field.

[field index]_type : The field index should be the index of the field on the ROS message from 1 to num_fields. It expects one of the types available (list of types above). Each type might expect more variables following the same syntax (also explained on the list above): [field index]_msg and/or [field index]_mux.

List of types:

That's it! In the end you'll have a bottle with the right structure to be sent to a ROS topic.

Be careful to match the data with what ROS expects to receive... If you set a list type and ROS is waiting for a vector of integers your [field index]_msg should be something like [field index]_msg = 1 , 2 , 3 , 4. In case you specify something like [field index]_msg = "hey" , "there" the conversion will fail because it cannot cast the values to integers.

Example

// ROS message examples: Example1.msg, Example2.msg and std_msgs/Header.msg 
//// 
// begin Example1.msg
//  std_msgs/Header header
//  string[] first_last_name
//  float64[] readings
// end Example1.msg
////
////
// begin Example2.msg
//  float64 random_number
// end Example2.msg
////
////
// begin Header.msg
//  uint32 seq
//  time stamp
//  string frame_id
//  Example2 other_example
// end Header.msg
////

// Imagine that the output topic is waiting for a message of the type Example1.msg.
// That means our `[message]` section should match the Example1.msg

[message]
num_fields = 3
1_type = msg
1_msg = header_message
2_type = list
2_msg = "Miguel" , "Aragão"
3_type = mux
3_mux = mux2

[header_message]
num_fiels = 4
1_type = counter
2_type = timestamp
3_type = single_value
3_msg = "0"
4_type = msg
4_msg = random_number_message

[random_number_message]
num_fields = 1
1_type = single_value
1_msg = 31.45

Conclusion

You're ready to customize your own configuration file! On the $BOTTLE_GENERATOR_DIR/app you'll find examples of the .ini files. Create your own file for your particular use-case.

Customize it yourself and I'll be glad to help you on any problem you might have!

Please open an issue for doubts and all kinds of feedback.