例程学习
自定义qrviz
1.cmakelist添加rviz依赖
# qt_build provides the qt cmake glue, roscpp the comms for a default talker
find_package(catkin REQUIRED COMPONENTS roscpp sensor_msgs
cv_bridge
std_msgs
image_transport
rviz
)
2.添加自定义qrviz类
头文件命名为*.hpp,避免可能的闪退
修改新增类文件所在目录到响应目录下,重新编译,如果还是找不到hpp文件重启qt
3.初始化
//创建rviz panel
render_panel_=new rviz::RenderPanel();
//向layout添加
layout->addWidget(render_panel_);
//创建rviz控制对象
manager_=new rviz::VisualizationManager(render_panel_);
tool_manager_=manager_->getToolManager();
ROS_ASSERT(manager_!=NULL);//防止闪退bug
//初始化render_panel 实现放大缩小等操作
render_panel_->initialize(manager_->getSceneManager(),manager_);
manager_->setFixedFrame("map");
//初始化rviz控制对象
manager_->initialize();
manager_->startUpdate();
manager_->removeAllDisplays();
4.创建display
void qrviz::Display_LaserScan(QString laser_topic,bool enable)
{
if(LaserScan_!=NULL)
{
delete LaserScan_;
LaserScan_=NULL;
}
LaserScan_=manager_->createDisplay("rviz/LaserScan","myLaser",enable);
LaserScan_->subProp("Topic")->setValue(laser_topic);
ROS_ASSERT(LaserScan_!=NULL);
}
librviz学习
以下内容均来自librviz源码
1.rviz::RenderPanel
渲染窗口,显示initialize传入的场景Ogre::SceneManager* scene_manager,并将鼠标以及键盘事件传递给可视化管理器DisplayContext* manager。接口如下
/**
* A widget which shows an OGRE-rendered scene in RViz.
*
* RenderPanel displays a scene and forwards mouse and key events to
* the DisplayContext (which further forwards them to the active
* Tool, etc.)
*/
/** Constructor. Ogre::Root::createRenderWindow() is called within. */
RenderPanel(QWidget* parent = nullptr);
~RenderPanel() override;
/** This sets up the Ogre::Camera for this widget. */
void initialize(Ogre::SceneManager* scene_manager, DisplayContext* manager);
2.rviz::VisualizationManager
- VisualizationManager 类是 rviz 的中心管理器类,包含所有显示、工具、ViewControllers 和其他管理器。
- 它保存主渲染窗口的当前视图控制器。
- 它有一个定时器,可在所有显示屏上调用 update()。 它创建并保存指向其他管理器对象的指针:选择管理器(SelectionManager)、框架管理器(FrameManager)、属性管理器(PropertyManager)和 Ogre::SceneManager 对象的指针。
以下为部分接口:
class RVIZ_EXPORT VisualizationManager : public DisplayContext : public QObject
/**
* \brief Constructor
* Creates managers and sets up global properties.
* @param render_panel a pointer to the main render panel widget of the app.
* @param wm a pointer to the window manager
* (which is really just a VisualizationFrame, the top-level container widget of rviz).
* @param tf_buffer an (optional) pointer to the tf2_ros::Buffer to be used by the FrameManager
* @param tf_listener an (optional) pointer to the tf2_ros::TransformListener to be used
* This listener's tf buffer needs to be the same as the passed tf_buffer!
* Both tf_buffer and tf_listener are automatically created if not provided.
*/
explicit VisualizationManager(
RenderPanel* render_panel,
WindowManagerInterface* wm = nullptr,
std::shared_ptr<tf2_ros::Buffer> tf_buffer = std::shared_ptr<tf2_ros::Buffer>(),
std::shared_ptr<tf2_ros::TransformListener> tf_listener =
std::shared_ptr<tf2_ros::TransformListener>());
/**
* \brief Do initialization that wasn't done in constructor.
* Initializes tool manager, view manager, selection manager.
*/
void initialize();
/**
* \brief Start timers.
* Creates and starts the update and idle timers, both set to 30Hz (33ms).
*/
void startUpdate();
/*
* \brief Stop the update timers. No Displays will be updated and no ROS
* callbacks will be called during this period.
*/
void stopUpdate();
/**
* \brief Create and add a display to this panel, by class lookup name
* @param class_lookup_name "lookup name" of the Display subclass, for pluginlib.
* Should be of the form "packagename/displaynameofclass", like "rviz/Image".
* @param name The name of this display instance shown on the GUI, like "Left arm camera".
* @param enabled Whether to start enabled
* @return A pointer to the new display.
*/
Display* createDisplay(const QString& class_lookup_name, const QString& name, bool enabled);
/**
* \brief Add a display to be managed by this panel
* @param display The display to be added
*/
void addDisplay(Display* display, bool enabled);
/**
* \brief Remove and delete all displays
*/
void removeAllDisplays();
/** @brief Load the properties of each Display and most editable rviz data.
*
* This is what is called when loading a "*.rviz" file.
*
* @param config The Config object to read from. Expected to be a Config::Map type.
* @sa save()
*/
void load(const Config& config);
/**
* \brief Save the properties of each Display and most editable rviz
* data.
*
* This is what is called when saving a "*.vcg" file.
* \param config The object to write to.
* \sa loadDisplayConfig()
*/
void save(Config config) const;
/** @brief Return the fixed frame name.
* @sa setFixedFrame() */
QString getFixedFrame() const override;
/** @brief Set the coordinate frame we should be transforming all fixed data into.
* @param frame The name of the frame -- must match the frame name broadcast to libTF
* @sa getFixedFrame() */
void setFixedFrame(const QString& frame);
/**
* @brief Convenience function: returns getFrameManager()->getTF2BufferPtr().
*/
std::shared_ptr<tf2_ros::Buffer> getTF2BufferPtr() const;
/**
* @brief Returns the Ogre::SceneManager used for the main RenderPanel.
*/
Ogre::SceneManager* getSceneManager() const override
{
return scene_manager_;
}
/**
* @brief Return the main RenderPanel.
*/
RenderPanel* getRenderPanel() const
{
return render_panel_;
}
/**
* @brief Return a pointer to the SelectionManager.
*/
SelectionManager* getSelectionManager() const override
{
return selection_manager_;
}
/** @brief Return a pointer to the ToolManager. */
ToolManager* getToolManager() const override
{
return tool_manager_;
}
/** @brief Return a pointer to the ViewManager. */
ViewManager* getViewManager() const override
{
return view_manager_;
}
/**
* @brief Return the window manager, if any.
*/
WindowManagerInterface* getWindowManager() const override
{
return window_manager_;
}
/** @brief Return the FrameManager instance. */
FrameManager* getFrameManager() const override
{
return frame_manager_;
}
/** @brief Return the current value of the frame count.
*
* The frame count is just a number which increments each time a
* frame is rendered. This lets clients check if a new frame has
* been rendered since the last time they did something. */
uint64_t getFrameCount() const override
{
return frame_count_;
}
/** @brief Return a factory for creating Display subclasses based on a class id string. */
DisplayFactory* getDisplayFactory() const override
{
return display_factory_;
}
PropertyTreeModel* getDisplayTreeModel() const
{
return display_property_tree_model_;
}
3.rviz::Display
例程实现Display基本都是用VisualizationManager::createDisplay
设置Display属性使用Property::subProp()->setValue(map_topic)
class RVIZ_EXPORT Display : public BoolProperty : public Property : public QObject
/**
* \brief Create and add a display to this panel, by class lookup name
* @param class_lookup_name "lookup name" of the Display subclass, for pluginlib.
* Should be of the form "packagename/displaynameofclass", like "rviz/Image".
* @param name The name of this display instance shown on the GUI, like "Left arm camera".
* @param enabled Whether to start enabled
* @return A pointer to the new display.
*/
Display* createDisplay(const QString& class_lookup_name, const QString& name, bool enabled);
/** @brief Return the first child Property with the given name, or
* the FailureProperty if no child has the name.
*
* If no child is found with the given name, an instance of a
* special Property subclass named FailureProperty is returned and
* an error message is printed to stdout.
* FailureProperty::subProp() always returns itself, which means you
* can safely chain a bunch of subProp() calls together and not have
* a crash even if one of the sub-properties does not actually
* exist. For instance:
*
* float width = prop->subProp( "Dimenshons" )->subProp( "Width" )->getValue().toFloat();
*
* If the first property @c prop has a "Dimensions" property but not
* a "Dimenshons" one, @c width will end up set to 0 and an error
* message will be printed, but the program will not crash here.
*
* This is an Order(N) operation in the number of subproperties. */
virtual Property* subProp(const QString& sub_name);