Note: This tutorial assumes that you have completed the previous tutorials: using rosed.
(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Criando arquivos msg e srv no ROS

Description: Este tutorial ensina como criar e construir (build) arquivos .msg e .srv assim como as linhas de comando de atalho: rosmsg, rossrv and roscp.

Tutorial Level: BEGINNER

Next Tutorial: Writing a simple publisher and subscriber (python) (c++)

Introdução a msg e srv

  • msg: os arquivos msg são arquivos de texto que descrevem os campos de uma mensagem ROS. Eles são usados para geração do código fonte em diferentes linguagens de programação.

  • srv: os arquivos srv descrevem os campos de um serviço ROS da mesma forma, sendo composto por duas partes: uma requisição (request) e uma resposta (response)

Arquivos msg são armazenados no diretório msg do pacote, assim como os arquivos srv são armazenados no diretório srv.

msg são simples arquivos de texto contendo um campo de tipo e um campo de nome por linha. Os campos de tip

  • int8, int16, int32, int64 (além de uint*)
  • float32, float64
  • string
  • time, duration
  • outros arquivos de msg
  • array[] de tamanho variável e array[C] de tamanho fixo

Existe também um tipo especial no ROS: Header. O header contém informações de timestamp e das coordenada do frame que são comumente usados no ROS. Você verá frequentemente a primeira linha do arquivo msg ter Header header.

Segue abaixo um exemplo de uma msg que usa o Header, um tipo string primitivo e mais duas outras mensagens:

  Header header
  string child_frame_id
  geometry_msgs/PoseWithCovariance pose
  geometry_msgs/TwistWithCovariance twist

Arquivos srv são similares aos arquivos msg, com a diferença de que eles contém duas partes: uma requisição(request) e uma resposta(response). As duas parte são separadas por uma linha '---'. Segue abaixo um exemplo de um arquivo srv:

int64 A
int64 B
---
int64 Sum

No exemplo acima, A e B pertencem à requisição e Sum pertence à resposta.

Utilizando msg

Criando uma msg

Vamos definir uma nova msg dentro do pacote que foi criado no tutorial anterior.

$ cd ~/catkin_ws/src/beginner_tutorials
$ mkdir msg
$ echo "int64 num" > msg/Num.msg

O exemplo do arquivo .msg acima contém apenas uma linha. Você pode criar um arquivo mais complexo adicionando novos elementos, sempre um por linha, como esse:

string first_name
string last_name
uint8 age
uint32 score

Além disso, existe mais um passo. Nós precisamos ter certeza que o arquivo msg foi gerado em código-fonte para C++, Python e outras linguagens:

Abra o package.xml e tenha certeza que essas duas linhas estão inclusas e descomente-as:

  <build_depend>message_generation</build_depend>
  <run_depend>message_runtime</run_depend>

Perceba que em tempo de montagem precisamos do "message_generation", enquanto que durante a execução precisamos apenas do "message_runtime"

Abra o CMakeLists.txt em seu editor de texto favorito (rosed abordado no tutorial anterior é uma boa opção).

Adicione a dependência message_generation na chamada find_package que já existe no seu CMakeLists.txt para que você possa gerar novas mensagens. Você pode fazer isso adicionando "message_generation" na lista COMPONENTS, ficando da seguinte forma:

# Não adicione esse texto no seu CMakeLists.txt. Modifique o texto existente para adicionar message_generation antes do fechamento do parênteses.

find_package(catkin REQUIRED COMPONENTS
   roscpp
   rospy
   std_msgs
   message_generation
)

Você pode perceber que às vezes seu projeto é montado sem problemas mesmo quando você não configura corretamente o find_package com todas as dependências. Isso acontece pois o catkin combina todos seus projetos em apenas um. Logo, se um outro projeto chama a mesma dependência no find_package, o seu pacote é configurado com os mesmo valores. Contudo esquecer esse passo irá quebrar seu projeto quando construído de forma isolada.

Além disso, exporte a dependência message_runtime:

catkin_package(
  ...
  CATKIN_DEPENDS message_runtime ...
  ...)

Ache o bloco de código seguinte:

# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

Descomente

Uncomment it by removing the # symbols and then replace the stand in Message*.msg files with your .msg file, such that it looks like this:

add_message_files(
  FILES
  Num.msg
)

By adding the .msg files manually, we make sure that CMake knows when it has to reconfigure the project after you add other .msg files.

Now we must ensure the generate_messages() function is called.

For ROS Hydro and later, you need to uncomment these lines:

# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )
  • so it looks like:
    generate_messages(
      DEPENDENCIES
      std_msgs
    )

In earlier versions, you may just need to uncomment one line:

generate_messages()

$ roscd beginner_tutorials
$ mkdir msg
$ echo "int64 num" > msg/Num.msg

The example above is the simplest, where the .msg file contains only 1 line. You can, of course, create more complex files by adding multiple elements per line like this:

string first_name
string last_name
uint8 age
uint32 score

There's one more step, though. We need to make sure that the msg files are turned into source code for C++, Python, and other languages. Open CMakeLists.txt in your favorite text editor (rosed from the previous tutorial is a good option) and remove # to uncomment the following line:

# rosbuild_genmsg()

Now you're ready to generate source files from your msg definition. If you want to do so right now, skip next sections to Common step for msg and srv.

Using rosmsg

That's all you need to do to create a msg. Let's make sure that ROS can see it using the rosmsg show command.

Usage:

$ rosmsg show [message type]

Example:

$ rosmsg show beginner_tutorials/Num

You will see:

  • int64 num

In the previous example, the message type consists of two parts:

  • beginner_tutorials -- the package where the message is defined

  • Num -- The name of the msg Num.

If you can't remember which Package a msg is in, you can leave out the package name. Try:

$ rosmsg show Num

You will see:

  • [beginner_tutorials/Num]:
    int64 num

Using srv

Creating a srv

Let's use the package we just created to create a srv:

$ roscd beginner_tutorials
$ mkdir srv

Instead of creating a new srv definition by hand, we will copy an existing one from another package.

For that, roscp is a useful commandline tool for copying files from one package to another.

Usage:

$ roscp [package_name] [file_to_copy_path] [copy_path]

Now we can copy a service from the rospy_tutorials package:

$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv

There's one more step, though. We need to make sure that the srv files are turned into source code for C++, Python, and other languages.

Unless you have done so already, open package.xml, and make sure these two lines are in it and uncommented:

  <build_depend>message_generation</build_depend>
  <run_depend>message_runtime</run_depend>

As before, note that at build time, we need "message_generation", while at runtime, we only need "message_runtime".

Unless you have done so already for messages earlier, add the message_generation dependency to generate messages in CMakeLists.txt:

# Do not just add this line to your CMakeLists.txt, modify the existing line
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation)

(Despite its name, message_generation works for both msg and srv.)

Also you need the same changes to package.xml for services as for messages, so look above for the additional dependencies required.

Remove # to uncomment the following lines:

# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

And replace the placeholder Service*.srv files for your service files:

add_service_files(
  FILES
  AddTwoInts.srv
)

Once again, open CMakeLists.txt and remove # to uncomment the following line:

# rosbuild_gensrv()

Now you're ready to generate source files from your service definition. If you want to do so right now, skip next sections to Common step for msg and srv.

Using rossrv

That's all you need to do to create a srv. Let's make sure that ROS can see it using the rossrv show command.

Usage:

$ rossrv show <service type>

Example:

$ rossrv show beginner_tutorials/AddTwoInts

You will see:

  • int64 a
    int64 b
    ---
    int64 sum

Similar to rosmsg, you can find service files like this without specifying package name:

$ rossrv show AddTwoInts
[beginner_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum

[rospy_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum

Common step for msg and srv

Next find this section in CMakeLists.txt:

# generate_messages(
#   DEPENDENCIES
# #  std_msgs  # Or other packages containing msgs
# )

Uncomment it and add any packages you depend on which contain .msg files that your messages use (in this case std_msgs), such that it looks like this:

generate_messages(
  DEPENDENCIES
  std_msgs
)

Now that we have made some new messages we need to make our package again:

# In your catkin workspace
$ cd ../..
$ catkin_make
$ cd -

Now that we have made some new messages we need to make our package again:

$ rosmake beginner_tutorials

Any .msg file in the msg directory will generate code for use in all supported languages. The C++ message header file will be generated in ~/catkin_ws/devel/include/beginner_tutorials/. The Python script will be created in ~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg. The lisp file appears in ~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/.

The full specification for the message format is available at the Message Description Language page.

Getting Help

We've seen quite a few ROS tools already. It can be difficult to keep track of what arguments each command requires. Luckily, most ROS tools provide their own help.

Try:

$ rosmsg -h
  • You should see a list of different rosmsg subcommands.

    Commands:
      rosmsg show Show message description
      rosmsg users  Find files that use message
      rosmsg md5  Display message md5sum
      rosmsg package  List messages in a package
      rosmsg packages List packages that contain messages

You can also get help for subcommands

$ rosmsg show -h
  • This shows the arguments that are needed for rosmsg show:
    Usage: rosmsg show [options] <message type>
    
    Options:
      -h, --help  show this help message and exit
      -r, --raw   show raw message text, including comments

Review

Lets just list some of the commands we've used so far:

  • rospack = ros+pack(age) : provides information related to ROS packages
  • roscd = ros+cd : changes directory to a ROS package or stack

  • rosls = ros+ls : lists files in a ROS package

  • roscp = ros+cp : copies files from/to a ROS package

  • rosmsg = ros+msg : provides information related to ROS message definitions
  • rossrv = ros+srv : provides information related to ROS service definitions
  • catkin_make : makes (compiles) a ROS package
    • rosmake = ros+make : makes (compiles) a ROS package (if you're not using a catkin workspace)

Next Tutorial

Now that you've made a new ROS msg and srv, let's look at writing a simple publisher and subscriber (python) (c++).

Wiki: pt_BR/ROS/Tutorials/CreatingMsgAndSrv (last edited 2020-04-18 23:31:53 by hbaqueiro)