上一节,可视化点云案例常用于显示深度视觉或三维激光雷达数据,那么rviz是否支持输入呢?
InteractiveMarker
官方示例代码(C++):
- /*
- * Copyright (c) 2011, Willow Garage, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the Willow Garage, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
- #include
-
- #include
-
- #include
-
- #include
-
-
- using namespace visualization_msgs;
-
- boost::shared_ptr
server; -
- std::vector< tf::Vector3 > positions;
-
- void processFeedback( const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
- {
- switch ( feedback->event_type )
- {
- case visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE:
- {
- //compute difference vector for this cube
-
- tf::Vector3 fb_pos(feedback->pose.position.x, feedback->pose.position.y, feedback->pose.position.z);
- unsigned index = atoi( feedback->marker_name.c_str() );
-
- if ( index > positions.size() )
- {
- return;
- }
- tf::Vector3 fb_delta = fb_pos - positions[index];
-
- // move all markers in that direction
- for ( unsigned i=0; i
size(); i++ ) - {
- float d = fb_pos.distance( positions[i] );
- float t = 1 / (d*5.0+1.0) - 0.2;
- if ( t < 0.0 ) t=0.0;
-
- positions[i] += t * fb_delta;
-
- if ( i == index ) {
- ROS_INFO_STREAM( d );
- positions[i] = fb_pos;
- }
-
- geometry_msgs::Pose pose;
- pose.position.x = positions[i].x();
- pose.position.y = positions[i].y();
- pose.position.z = positions[i].z();
-
- std::stringstream s;
- s << i;
- server->setPose( s.str(), pose );
- }
-
-
- break;
- }
- }
- server->applyChanges();
- }
-
- InteractiveMarkerControl& makeBoxControl( InteractiveMarker &msg )
- {
- InteractiveMarkerControl control;
- control.always_visible = true;
- control.orientation_mode = InteractiveMarkerControl::VIEW_FACING;
- control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
- control.independent_marker_orientation = true;
-
- Marker marker;
-
- marker.type = Marker::CUBE;
- marker.scale.x = msg.scale;
- marker.scale.y = msg.scale;
- marker.scale.z = msg.scale;
- marker.color.r = 0.2+0.7*msg.pose.position.x;
- marker.color.g = 0.2+0.7*msg.pose.position.y;
- marker.color.b = 0.2+0.7*msg.pose.position.z;
- marker.color.a = 1.0;
-
- control.markers.push_back( marker );
- msg.controls.push_back( control );
-
- return msg.controls.back();
- }
-
-
- void makeCube( )
- {
- int side_length = 10;
- float step = 1.0/ (float)side_length;
- int count = 0;
-
- positions.reserve( side_length*side_length*side_length );
-
- for ( double x=-0.5; x<0.5; x+=step )
- {
- for ( double y=-0.5; y<0.5; y+=step )
- {
- for ( double z=0.0; z<1.0; z+=step )
- {
- InteractiveMarker int_marker;
- int_marker.header.frame_id = "base_link";
- int_marker.scale = step;
-
- int_marker.pose.position.x = x;
- int_marker.pose.position.y = y;
- int_marker.pose.position.z = z;
-
- positions.push_back( tf::Vector3(x,y,z) );
-
- std::stringstream s;
- s << count;
- int_marker.name = s.str();
-
- makeBoxControl(int_marker);
-
- server->insert( int_marker );
- server->setCallback( int_marker.name, &processFeedback );
-
- count++;
- }
- }
- }
- }
-
- int main(int argc, char** argv)
- {
- ros::init(argc, argv, "cube");
-
- server.reset( new interactive_markers::InteractiveMarkerServer("cube") );
-
- ros::Duration(0.1).sleep();
-
- ROS_INFO("initializing..");
- makeCube();
- server->applyChanges();
- ROS_INFO("ready.");
-
- ros::spin();
-
- server.reset();
- }
如果需要在rviz中显示并测试,步骤如下:
01-
02-
int_marker.header.frame_id = "base_link";
03-
背景色改为浅白色
04-
查看
部分终端数据:
shiyanlou:demo_ws/ $ rosrun interactive_marker_tutorials cube [22:11:38]
[ERROR] [1661955135.491224279]: [registerPublisher] Failed to contact master at [localhost:11311]. Retrying...
[ INFO] [1661955142.587063541]: Connected to master at [localhost:11311]
[ INFO] [1661955142.698239311]: initializing..
[ INFO] [1661955142.711385709]: ready.
[ INFO] [1661955433.851128054]: 2.35608e-08
[ INFO] [1661955433.862355866]: 0.455605
[ INFO] [1661955433.985751109]: 0
[ INFO] [1661955434.060073593]: 0.0117029
[ INFO] [1661955434.147889679]: 0.0464634
[ INFO] [1661955434.224687924]: 0.011576
[ INFO] [1661955434.317503688]: 0.140218
[ INFO] [1661955434.375525722]: 0.0114497
[ INFO] [1661955434.456775907]: 0
[ INFO] [1661955434.533680882]: 0
[ INFO] [1661955434.614335283]: 0
[ INFO] [1661955434.666641382]: 0
[ INFO] [1661955434.744000213]: 0
[ INFO] [1661955434.821070352]: 0
[ INFO] [1661955434.902700050]: 0
[ INFO] [1661955434.951841464]: 0
[ INFO] [1661955435.033664385]: 0
[ INFO] [1661955435.115341065]: 0.0351378
[ INFO] [1661955435.172467772]: 0.0694076
[ INFO] [1661955435.250404696]: 0.070476
[ INFO] [1661955435.340758065]: 0.046382
[ INFO] [1661955435.418613802]: 0.0348074
[ INFO] [1661955435.474156388]: 0.0230308
[ INFO] [1661955435.556194217]: 0.0115739
[ INFO] [1661955435.636080060]: 0
[ INFO] [1661955435.713566499]: 0.0117843
[ INFO] [1661955435.768091911]: 0.0349274
[ INFO] [1661955435.854893311]: 0.0351311
[ INFO] [1661955435.930366401]: 0
[ INFO] [1661955436.015312457]: 0.034488
[ INFO] [1661955436.072866533]: 0.0121057
[ INFO] [1661955436.157107743]: 0.0465924
[ INFO] [1661955436.236680402]: 0
[ INFO] [1661955436.314375243]: 0
[ INFO] [1661955436.366920278]: 0
[ INFO] [1661955436.447782631]: 0
[ INFO] [1661955436.525610924]: 0
[ INFO] [1661955436.604214948]: 0
[ INFO] [1661955436.658894075]: 0.0117842
[ INFO] [1661955436.745685687]: 0.070666
稍作修改:
CYLINDER
小结:
在 RViz 中,执行以下操作:
将固定坐标设置为“/base_link”。
通过单击“显示”面板中的“添加”来添加“交互式标记”显示。将此显示的更新主题设置为“/basic_controls/update”。 这应该会立即在 rviz 中调出几个灰色立方体。
现在在工具面板中选择“交互”。 这将启用主视图中的所有交互元素,这将在框周围显示额外的箭头和环。 您可以左键单击这些控件,在某些情况下还可以单击框本身来更改每个交互式标记的姿势。 一些标记有一个上下文菜单,可以通过右键单击它们来访问它。
添加“网格”显示。 这是一个有用的视觉线索,可以帮助在拖动标记时了解它们在空间中的移动方式。
- /*
- * Copyright (c) 2011, Willow Garage, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the Willow Garage, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
- // %Tag(fullSource)%
- #include
-
- #include
-
- void processFeedback(
- const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
- {
- ROS_INFO_STREAM( feedback->marker_name << " is now at "
- << feedback->pose.position.x << ", " << feedback->pose.position.y
- << ", " << feedback->pose.position.z );
- }
-
- int main(int argc, char** argv)
- {
- ros::init(argc, argv, "simple_marker");
-
- // create an interactive marker server on the topic namespace simple_marker
- interactive_markers::InteractiveMarkerServer server("simple_marker");
-
- // create an interactive marker for our server
- visualization_msgs::InteractiveMarker int_marker;
- int_marker.header.frame_id = "base_link";
- int_marker.header.stamp=ros::Time::now();
- int_marker.name = "my_marker";
- int_marker.description = "Simple 1-DOF Control";
-
- // create a grey box marker
- visualization_msgs::Marker box_marker;
- box_marker.type = visualization_msgs::Marker::CUBE;
- box_marker.scale.x = 0.45;
- box_marker.scale.y = 0.45;
- box_marker.scale.z = 0.45;
- box_marker.color.r = 0.5;
- box_marker.color.g = 0.5;
- box_marker.color.b = 0.5;
- box_marker.color.a = 1.0;
-
- // create a non-interactive control which contains the box
- visualization_msgs::InteractiveMarkerControl box_control;
- box_control.always_visible = true;
- box_control.markers.push_back( box_marker );
-
- // add the control to the interactive marker
- int_marker.controls.push_back( box_control );
-
- // create a control which will move the box
- // this control does not contain any markers,
- // which will cause RViz to insert two arrows
- visualization_msgs::InteractiveMarkerControl rotate_control;
- rotate_control.name = "move_x";
- rotate_control.interaction_mode =
- visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
-
- // add the control to the interactive marker
- int_marker.controls.push_back(rotate_control);
-
- // add the interactive marker to our collection &
- // tell the server to call processFeedback() when feedback arrives for it
- server.insert(int_marker, &processFeedback);
-
- // 'commit' changes and send to all clients
- server.applyChanges();
-
- // start the ROS main loop
- ros::spin();
- }
- // %Tag(fullSource)%
引用(wiki.ros.org/rviz/Tutorials/):
交互式标记类似于前面教程中描述的“常规”标记,但是它们允许用户通过更改位置或旋转、单击它们或从分配给每个标记的上下文菜单中选择某些内容来与它们进行交互。
它们由visualization_msgs/InteractiveMarker 消息表示,该消息包含一个上下文菜单和几个控件(visualization_msgs/InteractiveMarkerControl)。这些控件定义了交互式标记的不同可视部分,可以由几个常规标记(visualization_msgs/Marker)组成,并且每个都可以具有不同的功能。
<
如果要创建提供一组交互式标记的节点,则需要实例化一个 InteractiveMarkerServer 对象。这将处理与客户端(通常是 RViz)的连接,并确保您所做的所有更改都被传输,并且您的应用程序被通知用户在交互式标记上执行的所有操作。
interactive_marker_architecture