Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Entorno de simulación
ROS/Gazebo
3.1 ROS
3.1.1 Introducción a ROS
Robot Operating System (ROS) es una plataforma software, lo que se
conoce como framework, para el desarrollo de software específico para ro-
bótica. Fue creado por el instituto de investigación Willow Garage en 2007
bajo licencia BSD y todos sus programas son de código abierto (OSS), per-
mitiéndose así su uso gratuito tanto para la investigación como para fines
comerciales.
65
66 ENTORNO DE SIMULACIÓN ROS/GAZEBO
Por otro lado, ROS nos proporciona también servicios estándares propios
de un sistema operativo pero sin serlo, ya que se instala sobre otro, en
general Linux y de manera recomendada Ubuntu, y por ello también recibe
la denominación de Meta-Sistema Operativo. Posee su propio manejador de
paquetes mediante comandos desde terminal para la gestión, compilación y
ejecución de archivos, así como abstracción de hardware[10].
Esto último hace que algunos paquetes de ROS sean en principio espe-
cíficos para este robot, pero, como se verá, una gran parte de ellos pueden
adaptarse y utilizarse a cualquier otro robot real o simulado, siempre que
ROS 67
Compilación
Para compilar un paquete en ROS se utiliza CMake, una plataforma de
código abierto para la generación, compilación y comprobación de paquetes
de software. Su uso es bastante sencillo, basta con que el paquete de ROS
contenga un archivo llamado CMakeLists.txt compuesto por una serie de
macros según lo que se quiera crear y compilar4 .
Obviando aquellas que por defecto aparecen para lanzar CMake y confi-
gurar la ubicación predeterminada para las salidas, las macros más comunes
que se utilizan son las siguientes:
$ rosmake nombre_paquete
<depend package=“nombre_paquete”>
Nodos
Un nodo es un módulo o proceso individual dentro del sistema de ROS
que realiza un cómputo, que puede enviar y/o recibir información de otros
nodos y usar y/u ofrecer servicios5 . Estos nodos no son más que los ejecuta-
bles de los paquetes de ROS ejecutándose. En la Figura 3.6 se muestra un
ejemplo de dos nodos, talker y listener en el que el primero está publicando
en un topic, denominado chatter, y el segundo está subscrito a él.
Cada nodo posee un nombre único, que lo identifica y lo distingue de
todos los demás nodos en ejecución. Así por ejemplo es posible lanzar el
4
http://www.ros.org/wiki/rosbuild/CMakeLists
5
http://www.ros.org/wiki/Nodes
ROS 71
mismo programa dos veces, lo que da lugar a dos nodos, siempre que éstos
tengan diferente nombres.
#include "ros/ros.h"
return 0;
}
“ros.h” contiene todas las cabeceras necesarias para el uso de las instruc-
ciones más comunes del sistema de ROS, como por ejemplo las referentes al
uso de los topics y servicios, pero no incluye los tipos de mensajes y otras
6
http://www.ros.org/wiki/roscpp
72 ENTORNO DE SIMULACIÓN ROS/GAZEBO
instrucciones.
Para ejecutar ciclos a una frecuencia deseada, por ejemplo para recibir
mensajes cada cierto tiempo ó controlar un robot, roscpp ofrece las siguien-
tes instrucciones:
ros::Rate r(10);
while (ros::ok()))
{
(Código a ejecutar...)
r.sleep();
}
“ros::Rate r(10)” permite especificar la frecuencia a la que se va a eje-
cutar el bucle while(). En este caso, se habría elegido una frecuencia de 10
Hz.
Topics
Los topics son buses por los cuales los nodos envían o reciben mensa-
jes. Simplemente un nodo debe comunicar al Master que desea publicar en
él para enviar información o suscribirse en él para recibir su información.
Pueden existir varios nodos publicando y varios nodos subscritos a la vez
en un mismo topic. Son anónimos, en el sentido de que los nodos publican
ó se suscriben a ellos pero nunca saben que otros nodos están publicando
o subscritos en el topic, lo cual desacopla la producción del consumo de la
información7 .
Todos los topics son unidireccionales, por lo cual un nodo que envía in-
formación por un topic nunca recibirá una respuesta directamente por el
7
http://www.ros.org/wiki/Topics
ROS 73
Un topic viene identificado por su nombre, que debe ser único y nor-
malmente es de la forma: “/nodo_que_lo_publica/nombre_topic”, aunque
esto es decisión del programador. A la hora de su declaración, además de
éste nombre, es necesario definir el tipo de mensaje que se va a enviar por
ellos y por tanto el tipo de mensaje que se va a recibir por ellos. El Master
no asegura esta concordancia, por lo cual ha de tenerse especial cuidado en
que al subscribirnos a un topic se haga con el tipo de mensaje que se está
enviando por éste.
Las funciones básicas que roscpp nos ofrece para anunciar que se va
publicar por un topic (creándose éste automáticamente si no existía) y
enviar datos son las del siguiente ejemplo:
#include "std_msgs/String.h"
(...)
#include "std_msgs/String.h"
(...)
Servicios
Los servicios en ROS son la forma en que se envía un mensaje (request)
desde un nodo a otro y éste le responde con otro mensaje (response):
Los servicios vienen definidos mediante los archivos .srv, que definen el
tipo de servicio que se va a ofrecer, esto es el tipo de mensaje que se va a
recibir como request y el tipo de mensaje que se va a devolver como respon-
se. Al igual que con los mensajes para los topics, ahora se deben incluir las
cabeceras auto-generadas por los archivos .srv del paquete en cuestión, que
contendrán las definiciones de las clases del tipo de servicio8 .
Las funciones básicas que roscpp nos ofrece para crear y ofrecer un ser-
vicio son las del siguiente ejemplo:
#include "Matematicas/SumaDosEnteros.h"
SumaDosEnteros:
int64 a
int64 b
—
int64 sum
Las dos partes del servicio, request y response, siempre vienen separadas
por el marcador “—”.
beginner_tutorials::AddTwoInts srv;
srv.request.a = 10;
srv.request.b = -3;
client.call(srv)
return 0;
}
La tercera sería un objeto de la clase del servicio, que contiene los miem-
bros request y response. Por último se rellena el objeto y se envía usando
la función “call()” del identificador.
Mensajes
Como ya se ha comentado, los nodos se comunican entre sí publicando y
recibiendo mensajes vía topics. Los mensajes son simplemente unas estruc-
turas de datos equivalentes a una estructura de C++ que se definen en la
carpeta msg de los paquetes mediante archivos de texto de extensión .msg
en forma de lista tipo-nombre10 :
Mensaje:
type1 name1
type2 name2
type3 name3
msg C++
bool uint8_t
int8 int8_t
uint8 uint8_t
int16 int16_t
uint16 uint16_t
int32 int32_t
uint32 uint32_t
int64 int64_t
uint64 uint64_t
float32 float
float64 double
string std::string
time ros::Time
duration ros::Duration
También pueden estar formados por otros tipos de mensajes (.msg) es-
tándares o ya definidos en std_msgs o en cualquier otro paquete de ROS,
siempre y cuando exista la dependencia oportuna entre paquetes. Por ejem-
10
http://www.ros.org/wiki/Messages
11
http://www.ros.org/wiki/msg
78 ENTORNO DE SIMULACIÓN ROS/GAZEBO
plo, el tipo de mensaje Header, del paquete std_msgs, se utiliza como enca-
bezamiento en multitud de tipos de mensajes y es estructura es la siguiente:
Header:
uint32 seq
time stamp
string frame_id
Por otro lado, se comentó que para los servicios se definían sus tipos en
los archivos .srv. Estos archivos son equivalentes a los .msg salvo en que se
componen de dos listas separadas por “—”, primero la lista de la estructura
de request y luego la de response. Obviamente estos archivos .srv se guardan
en su carpeta srv para que el compilador los encuentre y pueda crear sus
archivos de cabecera.
Master
El Master (o roscore) es un nodo que funciona de núcleo del sistema,
proporcionando una plataforma mediante el registro de nombres, servicios
y parámetros, sobre la cual se hace posible la comunicación y el envío de
datos entre los diferentes nodos individuales del sistema. Sin él los nodos no
se “encontrarían” entre ellos.
El Servidor de Parámetros.
Como ejemplo, véase en la Figura 3.10 como los dos nodos, uno (cámara)
que envía imágenes y otro que las recibe, se dirigen antes al Master para
crear y buscar, respectivamente, el topic antes de iniciar la comunicación
entre ellos12 .
$ roscore
Lanzadores
Como veremos en el siguiente apartado, es posible ejecutar nodos, llamar
a servicios y leer o publicar en topics directamente desde una terminal. Sin
embargo, si lo que se desea es lanzar varios nodos a la vez, cargar una
serie de parámetros o ejecutar varias herramientas, esa no sería la mejor
opción ya que habría que hacerlo uno por uno. Por esta razón existe en ROS
una herramienta denominada roslaunch, que permite fácilmente lanzar
múltiples nodos con sus argumentos, establecer una serie de parámetros en
el servidor y otras opciones bastante interesantes directamente tomándolos
de unos archivos de configuración de extensión .launch. Así simplemente
habría que lanzar desde una terminal:
<include file=“$ (find paquete que lo contiene)/ ruta hacia él/ achi-
vo.xml”>
<param>: Permite definir un parámetro en el Servidor de Parámetros.
Este parámetro puede ser un valor numérico constante:
Existen otros posibles tags pero no han sido usados en este proyecto.
Pueden verse en la wiki de ROS.
$ roscd [paquete]
$ rosls [paquete]
$ rosmake [paquete]
Para obtener más información acerca de que comandos tiene cada he-
rramienta y su forma de uso, puede consultarse el archivo ROScheats-
heet.pdf [11] en la página inicial de ROS o, directamente desde una termi-
nal, podemos escribir:
$ [herramienta] -h
$ [herramienta] [comando] -h
14
http://www.ros.org/wiki/APIs
ROS 83
Existen muchos más paquetes y pilas con diferentes utilidades, pero que
escapan del alcance de este proyecto.
<robot name="manipulador">
<link> ... </link>
<link> ... </link>
<link> ... </link>
</link>
Aunque luego se verán los joints, para aclarar la cuestión de las locali-
zaciones de los sistemas de referencias, hay que indicar que el sistema de
referencia del joint antecesor de cada link se encuentra siempre en el origen
visual del link, que situado en el punto donde se encontraba en el programa
que se modeló, en este caso Solid Edge, y que en la figura Figura 3.12 sería
el “link origen”, de color negro.
Dentro de cada bloque habrá que definir una serie de parámetros y es-
pecificaciones para el eslabón:
Por otro lado, a cada joint es posible asociarle un actuador y una transmi-
sión entre ambos, que además serán necesarios para añadirle un controlador
como veremos en el paquete para controlar el manipulador. Para ello, la
descripción URDF posee la etiqueta <transmission>:
<transmission name ="Transmision_1" type ="SimpleTransmission">
<actuator name="actuador_1" />
<joint name="art_12" />
<mechanicalReduction>1</mechanicalReduction>
</transmission>
17
http://www.ros.org/wiki/pr2_controller_manager/safety_limits
ROS 89
Por último, comentar dos utilidades más que presenta este stack y se
han usado en este proyecto:
check_urdf : Permite validar robots en formato URDF, devolviendo
si existe algún error en la descripción que le pasemos como argumento.
Para ello se ecribe una terminal algo similar a lo siguiente:
Common_msgs
Common_msgs es un stack que contiene una colección de mensajes que
son utilizados por un gran número de paquetes de ROS directamente o indi-
rectamente, es decir, para crear otro tipos de mensajes a partir de ellos. De
90 ENTORNO DE SIMULACIÓN ROS/GAZEBO
Para los programas que se crearán en este proyecto nos interesan aquellos
que están agrupados en el paquete geometry_msgs18 , que contiene men-
sajes para primitivas geométricas tales como puntos, vectores, posiciones,
orientaciones, velocidades y fuerzas. En concreto, se utilizan los siguientes
mensajes directamente y para crear otros mensajes:
Point:
float64 x
float64 y
float64 z
Vector3:
float64 x
float64 y
float64 z
Quaternion:
float64 x
float64 y
float64 z
float64 w
Pose:
Point position
Quaternion orientation
Twist:
Vector3 linear
Vector3 angular
Wrench:
Vector3 force
Vector3 torque
PoseWithCovariance:
Pose pose
float64[36] covariance
TwistWithCovariance:
Twist twist
float64[36] covariance
WrenchStamped:
Header header
Wrench wrench
Para poder utilizar estos tipos de mensajes, o crear otro tipo de men-
sajes en base a estos, es necesario incluir la dependencia a este paquete
(geometry_msgs) en el archivo manifest.xml del paquete donde se vaya
a crear el programa que lo utilize. Por ejemplo, para utilizar cualquiera de
los tipos anteriores es necesario añadir:
<depend package="geometry_msgs"/>
Gracias a esto será posible incluir el archivo de cabecera donde se define
el tipo de mensaje y crear variables del mismo tipo.
Esto ocurre en general con todos los paquetes que se vayan a utilizar en
un programa ejecutable en el sistema ROS, ya sea para tipos de mensajes,
tipos de servicios o cualquier función o clase que se quiera utilizar esté
definida en otro programa.
Roscpp - Time
En el apartado conceptos básicos ya se han comentado y ejemplificado
las clases y funciones que nos ofrece este paquete en cuanto a los nodos,
topics y servicios. Sin embargo, no se ha tratado todavía nada relaciona-
do con el acceso al tiempo o reloj real (wall time) o al tiempo de simulación.
time/duration
int32 sec
int32 nsec
ros::Time::waitForValid();
Control Toolbox
Control_toolbox es un paquete perteneciente a pr2_controller, un stack
que recopila diversos paquetes para el control del robot PR2 pero que pue-
den ser utilizados, en parte, para otros robots. Entre estos se encuentra
control_toolbox, que contiene una serie de clases C++ útiles para imple-
mentar controladores de una manera sencilla y para cualquier robot21 .
20
http://www.ros.org/wiki/roscpp/Overview/Time
21
http://www.ros.org/wiki/control_toolbox
94 ENTORNO DE SIMULACIÓN ROS/GAZEBO
Esto se debe a que, en esta clase, se supone que el error viene definido
también cambiado de signo respecto a su forma estandar:
e = V alor actual − V alor deseado
Los términos del controlador son los siguientes:
Término proporcional (P): Producto del error por el coeficiente de
proporcionalidad (p):
P = p ⋅ e(k)
I = i ⋅ int_e(k)
D = d ⋅ e(k)−e(k−1)
dt
22
http://www.ros.org/doc/api/control_toolbox/html/classcontrol__toolbox_1_1Pid.
html
ROS 95
Esta clase posee muchas más funciones miembro que no se van a tratar
aquí al no utilizarse para los controladores de nuestras robots. Pueden verse
todas ellas en la web referenciada en la segunda nota al pie de página, dos
páginas atrás.
Pr2_mechanism
namespace pr2_controller_interface
{
class Controller
{
public:
virtual bool init(pr2_mechanism_model::
RobotState *robot,
ros::NodeHandle &n);
virtual void starting();
virtual void update();
virtual void stopping();
bool getController(const std::string& name,
int sched,
ControllerType*& c);
};
}
Para crear nuestro controlador, basta con crear una clase que here-
de esta forma (sea una clase hija de la clase Controller ) y modificar
la definición de sus funciones miembros init(), starting(), update() y
stopping() según lo que deseemos que haga nuestro controlador.
de clase KDL::Chain.
Como siempre, este stack contiene más paquetes con tipos de mensajes
y herramientas de líneas de comandos que no han sido utilizados para nues-
tras aplicaciones, por lo que se obvian sus explicaciones para no cargar de
tanto contenido teórico el mismo.
rosbuild_add_library(control_manipulador_lib src/control.cpp)
control_nspace::ClaseControl,
pr2_controller_interface::Controller)
23
Si se desea más documentación sobre esta librería puede visitar la web de la misma: http:
//www.orocos.org/kdl
ROS 101
Para lo primero basta con ejecutar rviz y cargar el URDF del robot en
el Servidor de parámetros con el nombre robot_description. Una vez hecho
esto se puede se agregar el display denominado Robot model que permite
visualizar el modelo del robot cargado en el servidor tal y como se muestra
en la Figura 3.17.
Gráficas - rxplot
rxplot es una herramienta perteneciente al paquete rxtools del stack rx
que sirve para obtener gráficos en línea a partir de uno o varios topics.
Grafos - rxgraph
Con rxgraph se obtiene un gráfico de todos los procesos que se están eje-
cutando en ROS junto con sus conexiones, es decir, un grafo con los nodos
(elipses) y los topics (líneas) en ejecución.
Esta herramienta es de gran utilidad para saber que nodos están en eje-
cución y que relación tienen entre ellos, lo cual sirve también para ver si ha
fallado la ejecución de algún nodo o finalizado su ejecución. Aún así, tiene
el inconveniente de que no representa los servicios, por lo que este proyecto
carecerá en ocasiones de gráficos para ellos.
Se encuentra en el paquete rxgraph del stack rx, y como todos los ante-
riores sigue siendo un nodo más, aunque no aparecerá en su propio grafo y,
al igual que rxplot, está integrado en el sistema como herramienta de línea
106 ENTORNO DE SIMULACIÓN ROS/GAZEBO
$ rxgraph
Los tipos de mensajes que aparecen son aquellos que se estén enviando
desde los nodos mediante unas instrucciones del tipo:
ROS_INFO("Valor de x: [ %f ]",x);
3.2 Gazebo
3.2.1 Introducción a Gazebo
Gazebo, que nace con el nombre de Gazebo Project, es un simulador 3D,
cinemático, dinámico y multi-robot que permite realizar simulaciones de ro-
bots articulados en entornos complejos, interiores o exteriores, realistas y
tridimensionales[14].
<quickStepIters>10</quickStepIters>
<quickStepW>1.3</quickStepW>
<contactMaxCorrectingVel>100.0</contactMaxCorrectingVel>
<contactSurfaceLayer>0.001</contactSurfaceLayer>
</physics:ode>
Donde stepTime es el paso de integración del simulador, gravity es el vec-
tor de gravedad aplicado sobre cada cuerpo, cfm (constraint force mixing)
es un parámetro entre 0 y 1 que especifica la dureza de las restricciones de
los robots en cuanto a los contactos, de modo que mientras menor sea más
duras serán las restricciones y mientras mayor sea más blandas (permitien-
do cierta penetración entre dos cuerpos) y erp (error reduction parameter )
es otro parámetro entre 0 y 1 para reducir el posible error en las articulacio-
nes que, al integrar, haría que no se cumplan exactamente las restricciones
impuestas sobre ellas, debido a las posiciones/orientaciones de los cuerpos
que une. Las etiquetas en las que aparece quickStepIterestán relacionadas
con un nuevo método de integración, en el que no entraremos en este pro-
yecto, pero que agiliza la simulación. Por último, contactMaxCorrectingVel
que define la máxima velocidad entre contactos (por defecto sería infinita) y
contactSurfaceLayer que define una profundidad permitida de penetración
antes de estabilizarse un robot en el suelo, y que en caso de ser exactamente
cero puede no llegarse a esta estabilidad.
Por otro lado, Gazebo puede usar el reloj de simulación de ROS que se
publica como topic /clock , del que ya se hablado anteriormente, y al cual
se suscriben automáticamente los demás nodos que se ejecuten de forma que
compartan el mismo vector de tiempo. Gazebo es el que dirigirá el tiempo
de simulación, de tal forma que cuando la simulación se para, por lo que
también se para el reloj de la simulación, todos los demás nodos que se
estén ejecutando y usen éste reloj también se paran. Además, ha de tenerse
112 ENTORNO DE SIMULACIÓN ROS/GAZEBO
Los mensajes de tiempo que Gazebo envía por /clock tienen la misma
estructura que cualquier otro mensaje de tiempo: [sec, nsec], con el mismo
significado que para la clase ros::Time.
Gazebo, como nodo que es, publicará y se suscribirá a una serie de topics
al igual que ofrecerá al sistema una serie de servicios.
Los topics que ofrece y los topics a los que se suscribe por defecto son
los mostrados en el grafo de la Figura 3.25.
Como puede intuirse por sus nombres, todos están relacionados con el
estado (posiciones, parámetros y descripción) de los objetos existentes en el
simulador. Dado que usaremos los topics propios de los plugins, que se ve-
rán a continuación, para obtener este tipo de información, no se describirán
estos topics por defecto al no utilizarse en las aplicaciones de éste proyecto,
a excepción del ya comentado /clock.
Sin embargo, sí se usarán algunos de los servicios que Gazebo ofrece por
defecto, siendo el listado completo de servicios que ofrece el siguiente:
GAZEBO 113
/gazebo/apply_body_wrench
/gazebo/apply_joint_effort
/gazebo/clear_body_wrenches
/gazebo/clear_joint_forces
/gazebo/delete_model
/gazebo/get_joint_properties
/gazebo/get_link_properties
/gazebo/get_link_state
/gazebo/get_loggers
/gazebo/get_model_properties
/gazebo/get_model_state
/gazebo/get_physics_properties
/gazebo/get_world_properties
/gazebo/pause_physics
/gazebo/reset_simulation
/gazebo/reset_world
/gazebo/set_joint_properties
/gazebo/set_link_properties
/gazebo/set_link_state
/gazebo/set_logger_level
/gazebo/set_model_configuration
/gazebo/set_model_state
/gazebo/set_parameters
/gazebo/set_physics_properties
/gazebo/spawn_gazebo_model
/gazebo/spawn_urdf_model
/gazebo/unpause_physics
float64 z
geometry_msgs/Vector3 torque
float64 x
float64 y
float64 z
time start_time //Instante de aplicación duration
duration //Duración de aplicación
---
bool success //Devuelve true si no hubo error
string status_message
<gazebo>
<cotroller:tipo_plugin name = "..." plugin = "...">
<opción_1>...</opción_1>
(...)
<opción_n>...</opción_n>
</controller:tipo_plugin>
</gazebo>
Existen muchos plugins en el paquete gazebo_plugins, sin embargo aquí
vamos a centrarnos en los cuatro que se han utilizado para nuestras simu-
laciones:
1. GazeboRosTime: Plugin para publicar el tiempo de simulación vía
topic /clock. Su descripción XML es la siguiente:
<controller:gazebo_ros_time name="sim_time"
plugin="libgazebo_ros_time.so">
<alwaysOn>true</alwaysOn>
<updateRate>1000.0</updateRate>
</controller:gazebo_ros_time>
Este plugin al lanzar Gazebo no haría falta, ya que éste también hace
que se publique /clock. Sin embargo, se aconseja añadirlo para usar el
paquete pr2_controller_manager debido a que el plugin inicia un nodo
que controle el tiempo en caso que no exista ninguno como Gazebo.
Sus opciones son, en orden de aparición, la activación o desactivación
y la frecuencia (en Hz ) del topic /clock.
2. GazeboRosP3D: Plugin para la simulación de un sensor de posición
(GPS por ejemplo). Publica la localización de un cuerpo (link ) durante
116 ENTORNO DE SIMULACIÓN ROS/GAZEBO
<controller:gazebo_ros_p3d name="sensor_pos"
plugin="libgazebo_ros_p3d.so">
<alwaysOn>true</alwaysOn>
<updateRate>100</updateRate>
<bodyName>link_final</bodyName>
<frameName>link_base</frameName>
<topicName>sensor_odometria</topicName>
<gaussianNoise>0.0</gaussianNoise>
</controller:gazebo_ros_p3d>
Las dos primeras opciones son las mismas que en el plugin anterior.
Las dos siguientes serían el cuerpo (body) del que se lee la posición/o-
rientación y el sistema de referencia (frame) respecto al cual se mide.
Después se elige el nombre del topic de salida, y por último si se desea
añadir ruido a la medida.
Header header
uint32 seq
time stamp
string frame_id
string child_frame_id geometry_msgs/PoseWithCovariance pose
geometry_msgs/Pose pose
geometry_msgs/Point position
float64 x
float64 y
float64 z
geometry_msgs/Quaternion orientation
float64 x
float64 y
float64 z
float64 w
float64[36] covariance
geometry_msgs/TwistWithCovariance twist
geometry_msgs/Twist twist
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
GAZEBO 117
float64 z
float64[36] covariance
<controller:gazebo_ros_f3d name="sensor_F"
plugin="libgazebo_ros_f3d.so">
<alwaysOn>true</alwaysOn>
<updateRate>10</updateRate>
<bodyName>link_base</bodyName>
<frameName>link_base</frameName>
<topicName>esfuerzo_base</topicName>
<interface:position name="interfaz_interna" />
</controller:gazebo_ros_f3d>
<sensor:camera name="Camara_sensor">
<imageSize>640 480</imageSize>
<nearClip>0.01</nearClip>
<farClip>10</farClip>
<controller:gazebo_ros_camera name="Camara_controller"
plugin="libgazebo_ros_camera.so">
<alwaysOn>true</alwaysOn>
118 ENTORNO DE SIMULACIÓN ROS/GAZEBO
<updateRate>100.0</updateRate>
<imageTopicName>/ Camara/image_raw</imageTopicName>
<cameraInfoTopicName>/Camara/camera_info</cameraInfoTopicName>
<frameName>Camara</frameName>
</controller:gazebo_ros_camera>
</sensor:camera>
Nótese que el controlador esta vez, además de estar entre las etique-
tas de <gazebo>, está también dentro de las etiquetas de <sensor>,
donde además del controlador se está especificando la resolución, las
distancias más cercana y más lejana a las que los objetos aparecen en
la imagen. Las opciones del controlador son equivalentes a las de los
anteriores plugins salvo que ahora se publican dos topics: