mirror of
https://github.com/moveit/moveit_task_constructor.git
synced 2025-11-04 14:49:57 +08:00
Fix (again) creation of TaskPanel
This commit is contained in:
parent
f7ea72010b
commit
ef9c7612a9
@ -59,7 +59,7 @@
|
||||
|
||||
namespace moveit_rviz_plugin {
|
||||
|
||||
TaskDisplay::TaskDisplay() : Display(), received_task_description_(false) {
|
||||
TaskDisplay::TaskDisplay() : Display(), panel_requested_(false), received_task_description_(false) {
|
||||
task_list_model_.reset(new TaskListModel);
|
||||
|
||||
MetaTaskListModel::instance().insertModel(task_list_model_.get(), this);
|
||||
@ -88,17 +88,24 @@ TaskDisplay::TaskDisplay() : Display(), received_task_description_(false) {
|
||||
}
|
||||
|
||||
TaskDisplay::~TaskDisplay() {
|
||||
if (context_)
|
||||
TaskPanel::decDisplayCount();
|
||||
if (panel_requested_)
|
||||
TaskPanel::release(); // Indicate that we don't need a TaskPanel anymore
|
||||
}
|
||||
|
||||
void TaskDisplay::onInitialize() {
|
||||
Display::onInitialize();
|
||||
trajectory_visual_->onInitialize(scene_node_, context_);
|
||||
task_list_model_->setDisplayContext(context_);
|
||||
// create a new TaskPanel by default
|
||||
// by post-poning this to Qt's GUI loop, we can ensure that rviz has loaded everything before
|
||||
QTimer::singleShot(0, [this]() { TaskPanel::incDisplayCount(context_->getWindowManager()); });
|
||||
}
|
||||
|
||||
inline void TaskDisplay::requestPanel() {
|
||||
if (panel_requested_)
|
||||
return; // already done
|
||||
|
||||
// Create a new TaskPanel if not yet done.
|
||||
// This cannot be done in initialize(), because Panel loading follows Display loading in rviz.
|
||||
panel_requested_ = true;
|
||||
TaskPanel::request(context_->getWindowManager());
|
||||
}
|
||||
|
||||
void TaskDisplay::loadRobotModel() {
|
||||
@ -170,6 +177,7 @@ void TaskDisplay::calculateOffsetPosition() {
|
||||
}
|
||||
|
||||
void TaskDisplay::update(float wall_dt, float ros_dt) {
|
||||
requestPanel();
|
||||
Display::update(wall_dt, ros_dt);
|
||||
trajectory_visual_->update(wall_dt, ros_dt);
|
||||
}
|
||||
@ -188,6 +196,7 @@ void TaskDisplay::changedRobotDescription() {
|
||||
|
||||
void TaskDisplay::taskDescriptionCB(const moveit_task_constructor_msgs::TaskDescriptionConstPtr& msg) {
|
||||
setStatus(rviz::StatusProperty::Ok, "Task Monitor", "OK");
|
||||
requestPanel();
|
||||
task_list_model_->processTaskDescriptionMessage(*msg, update_nh_,
|
||||
base_ns_ + GET_SOLUTION_SERVICE "_" + msg->task_id);
|
||||
|
||||
|
||||
@ -100,6 +100,9 @@ protected:
|
||||
void fixedFrameChanged() override;
|
||||
void calculateOffsetPosition();
|
||||
|
||||
private:
|
||||
inline void requestPanel();
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* \brief Slot Event Functions
|
||||
@ -123,6 +126,7 @@ protected:
|
||||
std::unique_ptr<TaskSolutionVisualization> trajectory_visual_;
|
||||
// The TaskListModel storing actual task and solution data
|
||||
std::unique_ptr<TaskListModel> task_list_model_;
|
||||
bool panel_requested_;
|
||||
|
||||
// Load robot model
|
||||
rdf_loader::RDFLoaderPtr rdf_loader_;
|
||||
|
||||
@ -130,7 +130,25 @@ void TaskPanel::addSubPanel(SubPanel* w, const QString& title, const QIcon& icon
|
||||
connect(w, SIGNAL(configChanged()), this, SIGNAL(configChanged()));
|
||||
}
|
||||
|
||||
void TaskPanel::incDisplayCount(rviz::WindowManagerInterface* window_manager) {
|
||||
/* Realizing a singleton Panel is a nightmare with rviz...
|
||||
* Formally, Panels (as a plugin class) cannot be singleton, because new instances are created on demand.
|
||||
* Hence, we decided to use a true singleton for the underlying model only and a fake singleton for the panel.
|
||||
* Thus, all panels (in case multiple were created) show the same content.
|
||||
* The fake singleton shall ensure that only a single panel is created, even if several displays are created.
|
||||
* To this end, the displays request() the need for a panel during their initialization and they release()
|
||||
* this need during their destruction. This, in principle, allows to create a panel together with the first
|
||||
* display and destroy it when the last display is gone.
|
||||
* Obviously, the user can still decide to explicitly delete the panel (or create new ones).
|
||||
|
||||
* The nightmare arises from the order of loading of displays and panels: Displays are loaded first.
|
||||
* However, directly creating a panel with the first loaded display doesn't work, because panel loading
|
||||
* will create another panel instance later (because there is no singleton support).
|
||||
* Hence, we need to postpone the actual panel creation from displays until panel loading is finished as well.
|
||||
* This was initially done, by postponing panel creation to TaskDisplay::update(). However, update()
|
||||
* will never be called if the display is disabled...
|
||||
*/
|
||||
|
||||
void TaskPanel::request(rviz::WindowManagerInterface* window_manager) {
|
||||
++DISPLAY_COUNT;
|
||||
|
||||
rviz::VisualizationFrame* vis_frame = dynamic_cast<rviz::VisualizationFrame*>(window_manager);
|
||||
@ -143,7 +161,7 @@ void TaskPanel::incDisplayCount(rviz::WindowManagerInterface* window_manager) {
|
||||
assert(dock->widget() == SINGLETON);
|
||||
}
|
||||
|
||||
void TaskPanel::decDisplayCount() {
|
||||
void TaskPanel::release() {
|
||||
Q_ASSERT(DISPLAY_COUNT > 0);
|
||||
if (--DISPLAY_COUNT == 0 && SINGLETON)
|
||||
SINGLETON->deleteLater();
|
||||
|
||||
@ -91,8 +91,8 @@ public:
|
||||
* If not yet done, an instance is created. If use count drops to zero,
|
||||
* the global instance is destroyed.
|
||||
*/
|
||||
static void incDisplayCount(rviz::WindowManagerInterface* window_manager);
|
||||
static void decDisplayCount();
|
||||
static void request(rviz::WindowManagerInterface* window_manager);
|
||||
static void release();
|
||||
|
||||
void onInitialize() override;
|
||||
void load(const rviz::Config& config) override;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user