Rviz教程(二):Markers: Sending Basic Shapes (C++)

本文介绍如何使用 ROS 的 visualization_msgs/Marker 消息发送基本形状(立方体、球体、圆柱和箭头),并通过 rviz 实现可视化。通过不断循环发送不同类型的 Marker 来展示四种基本形状。

Markers: Sending Basic Shapes (C++)

Description:  Shows how to use  visualization_msgs/Marker  messages to send basic shapes (cube,  sphere (范围) cylinder (圆筒) , arrow) to rviz.

Tutorial Level:  BEGINNER

Next Tutorial:   Markers: Points and Lines  

Intro

Unlike other displays, the Marker Display lets you visualize(形象) data in rviz without rviz knowing anything about interpreting(说明) that data. Instead, primitive(原始的) objects are sent to the display through visualization_msgs/Markermessages, which let you show things like arrows, boxes, spheres(范围) and lines.

This tutorial(辅导的) will show you how to send the four basic shapes (boxes, spheres(范围)cylinders(圆筒), and arrows). We'll create a program that sends out a new marker every second, replacing the last one with a different shape.

Create a Package

Before getting started, let's create a package called using_markers, somewhere in your package path:

catkin_create_pkg using_markers roscpp visualization_msgs

Sending Markers

The Code

Paste(张贴) the following into src/basic_shapes.cpp:

https://raw.github.com/ros-visualization/visualization(形象化)_tutorials/indigo-devel/visualization_marker_tutorials/src/basic_shapes.cpp

切换行号显示
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>

int main( int argc, char** argv )
{
  ros::init(argc, argv, "basic_shapes");
  ros::NodeHandle n;
  ros::Rate r(1);
  ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("visualization_marker", 1);

  // Set our initial shape type to be a cube
  uint32_t shape = visualization_msgs::Marker::CUBE;

  while (ros::ok())
  {
    visualization_msgs::Marker marker;
    // Set the frame ID and timestamp.  See the TF tutorials for information on these.
    marker.header.frame_id = "/my_frame";
    marker.header.stamp = ros::Time::now();

    // Set the namespace and id for this marker.  This serves to create a unique ID
    // Any marker sent with the same namespace and id will overwrite the old one
    marker.ns = "basic_shapes";
    marker.id = 0;

    // Set the marker type.  Initially this is CUBE, and cycles between that and SPHERE, ARROW, and CYLINDER
    marker.type = shape;

    // Set the marker action.  Options are ADD, DELETE, and new in ROS Indigo: 3 (DELETEALL)
    marker.action = visualization_msgs::Marker::ADD;

    // Set the pose of the marker.  This is a full 6DOF pose relative to the frame/time specified in the header
    marker.pose.position.x = 0;
    marker.pose.position.y = 0;
    marker.pose.position.z = 0;
    marker.pose.orientation.x = 0.0;
    marker.pose.orientation.y = 0.0;
    marker.pose.orientation.z = 0.0;
    marker.pose.orientation.w = 1.0;

    // Set the scale of the marker -- 1x1x1 here means 1m on a side
    marker.scale.x = 1.0;
    marker.scale.y = 1.0;
    marker.scale.z = 1.0;

    // Set the color -- be sure to set alpha to something non-zero!
    marker.color.r = 0.0f;
    marker.color.g = 1.0f;
    marker.color.b = 0.0f;
    marker.color.a = 1.0;

    marker.lifetime = ros::Duration();

    // Publish the marker
    while (marker_pub.getNumSubscribers() < 1)
    {
      if (!ros::ok())
      {
        return 0;
      }
      ROS_WARN_ONCE("Please create a subscriber to the marker");
      sleep(1);
    }
    marker_pub.publish(marker);

    // Cycle between different shapes
    switch (shape)
    {
    case visualization_msgs::Marker::CUBE:
      shape = visualization_msgs::Marker::SPHERE;
      break;
    case visualization_msgs::Marker::SPHERE:
      shape = visualization_msgs::Marker::ARROW;
      break;
    case visualization_msgs::Marker::ARROW:
      shape = visualization_msgs::Marker::CYLINDER;
      break;
    case visualization_msgs::Marker::CYLINDER:
      shape = visualization_msgs::Marker::CUBE;
      break;
    }

    r.sleep();
  }
}

Now edit the CMakeLists.txt file in your using_markers package, and add:

add_executable(basic_shapes src/basic_shapes.cpp)
target_link_libraries(basic_shapes ${catkin_LIBRARIES})

to the bottom.

The Code Explained

Ok, let's break down the code piece by piece:

切换行号显示
  30 #include <ros/ros.h>
  31 #include <visualization_msgs/Marker.h>
  32 

You should have seen the ROS include by now. We also include the visualization_msgs/Marker message definition.

切换行号显示
  33 int main( int argc, char** argv )
  34 {
  35   ros::init(argc, argv, "basic_shapes");
  36   ros::NodeHandle n;
  37   ros::Rate r(1);
  38   ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("visualization_marker", 1);

This should look familiar. We initialize(初始化) ROS, and create a ros::Publisher on the visualization_marker topic.

切换行号显示
  41   uint32_t shape = visualization_msgs::Marker::CUBE;

Here we create an integer(整数) to keep track of what shape we're going to publish. The four types we'll be using here all use the visualization_msgs/Marker message in the same way, so we can simply switch(转换) out the shape type to demonstrate(证明) the four different shapes.

切换行号显示
  43   while (ros::ok())
  44   {
  45     visualization_msgs::Marker marker;
  46     // Set the frame ID and timestamp.  See the TF tutorials for information on these.
  47     marker.header.frame_id = "/my_frame";
  48     marker.header.stamp = ros::Time::now();

This begins the meat of the program. First we create a visualization_msgs/Marker, and begin filling it out. The header here is a roslib/Header, which should be familiar if you've done the tf tutorials. We set the frame_id member to /my_frame as an example. In a running system this should be the frame(有木架的) relative to which you want the marker's pose(造成) to be interpreted(说明).

切换行号显示
  52     marker.ns = "basic_shapes";
  53     marker.id = 0;

The namespace (ns) and id are used to create a unique(独特的) name for this marker. If a marker message is received with the same ns and id, the new marker will replace the old one.

切换行号显示
  56     marker.type = shape;

This type field is what specifies(指定) the kind of marker we're sending. The available types are enumerated(枚举) in the visualization_msgs/Marker message. Here we set the type to our shape variable(变量), which will change every time through the loop(环).

切换行号显示
  59     marker.action = visualization_msgs::Marker::ADD;

The action field is what specifies what to do with the marker. The options are visualization(形象化)_msgs::Marker::ADD and visualization_msgs::Marker::DELETEADD is something of a misnomer(用词不当), it really means "create or modify(修改)".

New in Indigo A new action has been added to delete all markers in the particular Rviz display, regardless(不管) of ID or namespace. The value is 3 and in future ROS version the message will change to have value visualization(形象化)_msgs::Marker::DELETEALL.

切换行号显示
  62     marker.pose.position.x = 0;
  63     marker.pose.position.y = 0;
  64     marker.pose.position.z = 0;
  65     marker.pose.orientation.x = 0.0;
  66     marker.pose.orientation.y = 0.0;
  67     marker.pose.orientation.z = 0.0;
  68     marker.pose.orientation.w = 1.0;

Here we set the pose(姿势) of the marker. The geometry_msgs/Pose message consists of a geometry_msgs/Vector3 to specify(指定) the position and a geometry_msgs/Quaternion to specify the orientation(方向). Here we set the position to the origin, and the orientation to the identity(身份) orientation (note the 1.0 for w).

切换行号显示
  71     marker.scale.x = 1.0;
  72     marker.scale.y = 1.0;
  73     marker.scale.z = 1.0;

Now we specify the scale(规模) of the marker. For the basic shapes, a scale of 1 in all directions means 1 meter on a side.

切换行号显示
  76     marker.color.r = 0.0f;
  77     marker.color.g = 1.0f;
  78     marker.color.b = 0.0f;
  79     marker.color.a = 1.0;

The color of the marker is specified(指定) as a std_msgs/ColorRGBA. Each member should be between 0 and 1. An alpha (a) value of 0 means completely transparent(透明的) (invisible(无形的)), and 1 is completely opaque(不透明的).

切换行号显示
  81     marker.lifetime = ros::Duration();

The lifetime field specifies how long this marker should stick around before being automatically(自动地) deleted. A value of ros::Duration() means never to auto-delete.

If a new marker message is received before the lifetime has been reached, the lifetime will be reset(重置) to the value in the new marker message.

切换行号显示
  84     while (marker_pub.getNumSubscribers() < 1)
  85     {
  86       if (!ros::ok())
  87       {
  88         return 0;
  89       }
  90       ROS_WARN_ONCE("Please create a subscriber to the marker");
  91       sleep(1);
  92     }
  93     marker_pub.publish(marker);

We wait for the marker to have a subscriber(订户) and we then publish the marker. Note that you can also use a latched publisher as an alternative(二中择一) to this code.

切换行号显示
  96     switch (shape)
  97     {
  98     case visualization_msgs::Marker::CUBE:
  99       shape = visualization_msgs::Marker::SPHERE;
 100       break;
 101     case visualization_msgs::Marker::SPHERE:
 102       shape = visualization_msgs::Marker::ARROW;
 103       break;
 104     case visualization_msgs::Marker::ARROW:
 105       shape = visualization_msgs::Marker::CYLINDER;
 106       break;
 107     case visualization_msgs::Marker::CYLINDER:
 108       shape = visualization_msgs::Marker::CUBE;
 109       break;
 110     }

This code lets us show all four shapes while just publishing the one marker message. Based on the current shape, we set what the next shape to publish will be.

Sleep and loop(打环) back to the top.

Building the Code

You should be able to build the code with:

$ cd %TOP_DIR_YOUR_CATKIN_WORKSPACE%
$ catkin_make

Running the Code

You should be able to run the code with:

rosrun using_markers basic_shapes

Viewing the Markers

Now that you're publishing markers, you need to set rviz up to view them. First, make sure rviz is built:

rosmake rviz

Now, run rviz:

rosrun using_markers basic_shapes
rosrun rviz rviz

If you've never used rviz before, please see the User's Guide to get you started.

The first thing to do, because we don't have any tf transforms(改变) setup(设置), is to set the Fixed Frames to the frame(框架) we set the marker to above, /my_frame. In order to do so, set the Fixed Frame(框架) field to "/my_frame".

Next add a Markers display. Notice that the default topic specified(指定)visualization_marker, is the same as the one being published.

You should now see a marker at the origin that changes shape every second: Basic Shapes

More Information

For more information on the different types of markers beyond the ones shown here, please see the Markers Display Page

### Vue.js 中使用 `v-bind` 绑定 scale 和 markers 属性 在 Vue.js 应用程序中,为了动态绑定组件或元素上的属性,可以利用 `v-bind` 指令。对于特定于地图应用中的 `scale` 和 `markers` 属性来说,可以通过 JavaScript 对象来管理这些属性的状态,并通过 `v-bind` 将其传递给子组件或者自定义的地图组件。 当处理像 Google Maps 或其他第三方地图库集成时,通常会有一个封装好的 Vue 地图组件,允许开发者以声明方式设置选项和交互逻辑。下面是一个假设的例子展示如何实现这一点: #### 使用 `v-bind` 动态绑定 `scale` 和 `markers` ```html <template> <!-- 假设存在一个名为 MapComponent 的地图组件 --> <MapComponent :options="mapOptions"></MapComponent> </template> <script setup> import { ref, reactive } from 'vue'; // 定义 mapOptions 来保存 scale 和 markers 配置 const mapOptions = reactive({ center: { lat: -34.397, lng: 150.644 }, zoom: 8, scaleControl: true, // 控制是否显示比例尺控件 markers: [ { position: { lat: -34.397, lng: 150.644 }, title: 'Marker Title' } ] }); </script> ``` 在这个例子中,`:options` 是缩写的写法代表 `v-bind:options`,它用于将整个 `mapOptions` 对象作为 props 发送给 `<MapComponent>`[^1]。如果要单独绑定 `scale` 和 `markers`,则可以直接这样做: ```html <MapComponent :scale-control="mapOptions.scaleControl" :markers="mapOptions.markers"></MapComponent> ``` 这里需要注意的是具体的属性名取决于所使用的地图组件 API 设计;上述代码片段仅作为一个通用指导示例[^2]。 #### 更新 marker 数据 每当需要更新标记列表时,只需修改 `mapOptions.markers` 数组即可触发视图重新渲染并反映最新的变化。由于采用了响应式设计模式 (`reactive`),任何对 `mapOptions` 内部状态的更改都会自动同步到 UI 上[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值