Skip to content

Commit

Permalink
NavSat (GPS) map plugin (#342)
Browse files Browse the repository at this point in the history
Signed-off-by: Louise Poubel <[email protected]>
  • Loading branch information
chapulina authored Jan 5, 2022
1 parent 879a8d1 commit 277f28b
Show file tree
Hide file tree
Showing 9 changed files with 484 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .github/ci/packages.apt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ qml-module-qt-labs-platform
qml-module-qt-labs-settings
qml-module-qtcharts
qml-module-qtgraphicaleffects
qml-module-qtlocation
qml-module-qtpositioning
qml-module-qtqml-models2
qml-module-qtquick-controls
qml-module-qtquick-controls2
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ set(IGN_RENDERING_VER ${ignition-rendering6_VERSION_MAJOR})

#--------------------------------------
# Find ignition-msgs
ign_find_package(ignition-msgs8 REQUIRED)
ign_find_package(ignition-msgs8 REQUIRED VERSION 8.2)
set(IGN_MSGS_VER ${ignition-msgs8_VERSION_MAJOR})

#--------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions Migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Deprecated code produces compile-time warnings. These warning serve as
notification to users that their code should be upgraded. The next major
release will remove the deprecated code.

## Ignition GUI 6.2 to 6.3

* New QML dependencies, only needed for the NavSatMap plugin: `qml-module-qtlocation`, `qml-module-qtpositioning`

## Ignition GUI 6.1 to 6.2

* All features from `Grid3D` have been incorportated into `GridConfig`. The code
Expand Down
1 change: 1 addition & 0 deletions src/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ add_subdirectory(plotting)
add_subdirectory(publisher)
add_subdirectory(marker_manager)
add_subdirectory(minimal_scene)
add_subdirectory(navsat_map)
add_subdirectory(scene3d)
add_subdirectory(screenshot)
add_subdirectory(tape_measure)
Expand Down
7 changes: 7 additions & 0 deletions src/plugins/navsat_map/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ign_gui_add_plugin(NavSatMap
SOURCES
NavSatMap.cc
QT_HEADERS
NavSatMap.hh
)

191 changes: 191 additions & 0 deletions src/plugins/navsat_map/NavSatMap.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
* Copyright (C) 2021 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "NavSatMap.hh"

#include <algorithm>
#include <iostream>
#include <limits>
#include <string>
#include <vector>

#include <ignition/common/Console.hh>
#include <ignition/plugin/Register.hh>
#include <ignition/transport/Node.hh>

#include "ignition/gui/Application.hh"

namespace ignition
{
namespace gui
{
namespace plugins
{
class NavSatMapPrivate
{
/// \brief List of topics publishing navSat messages.
public: QStringList topicList;

/// \brief Holds data to set as the next navSat
public: msgs::NavSat navSatMsg;

/// \brief Node for communication.
public: transport::Node node;

/// \brief Mutex for accessing navSat data
public: std::recursive_mutex navSatMutex;
};
}
}
}

using namespace ignition;
using namespace gui;
using namespace plugins;

/////////////////////////////////////////////////
NavSatMap::NavSatMap()
: Plugin(), dataPtr(new NavSatMapPrivate)
{
}

/////////////////////////////////////////////////
NavSatMap::~NavSatMap()
{
}

/////////////////////////////////////////////////
void NavSatMap::LoadConfig(const tinyxml2::XMLElement *_pluginElem)
{
// Default name in case user didn't define one
if (this->title.empty())
this->title = "Navigation satellite map";

std::string topic;
bool topicPicker = true;

// Read configuration
if (_pluginElem)
{
if (auto topicElem = _pluginElem->FirstChildElement("topic"))
topic = topicElem->GetText();

if (auto pickerElem = _pluginElem->FirstChildElement("topic_picker"))
pickerElem->QueryBoolText(&topicPicker);
}

if (topic.empty() && !topicPicker)
{
ignwarn << "Can't hide topic picker without a default topic." << std::endl;
topicPicker = true;
}

this->PluginItem()->setProperty("showPicker", topicPicker);

if (!topic.empty())
{
this->SetTopicList({QString::fromStdString(topic)});
this->OnTopic(QString::fromStdString(topic));
}
else
this->OnRefresh();
}

/////////////////////////////////////////////////
void NavSatMap::ProcessMessage()
{
std::lock_guard<std::recursive_mutex> lock(this->dataPtr->navSatMutex);

this->newMessage(this->dataPtr->navSatMsg.latitude_deg(),
this->dataPtr->navSatMsg.longitude_deg());
}

/////////////////////////////////////////////////
void NavSatMap::OnMessage(const msgs::NavSat &_msg)
{
std::lock_guard<std::recursive_mutex> lock(this->dataPtr->navSatMutex);
this->dataPtr->navSatMsg = _msg;

// Signal to main thread that the navSat changed
QMetaObject::invokeMethod(this, "ProcessMessage");
}

/////////////////////////////////////////////////
void NavSatMap::OnTopic(const QString _topic)
{
auto topic = _topic.toStdString();
if (topic.empty())
return;

// Unsubscribe
auto subs = this->dataPtr->node.SubscribedTopics();
for (auto sub : subs)
this->dataPtr->node.Unsubscribe(sub);

// Subscribe to new topic
if (!this->dataPtr->node.Subscribe(topic, &NavSatMap::OnMessage,
this))
{
ignerr << "Unable to subscribe to topic [" << topic << "]" << std::endl;
}
}

/////////////////////////////////////////////////
void NavSatMap::OnRefresh()
{
// Clear
this->dataPtr->topicList.clear();

// Get updated list
std::vector<std::string> allTopics;
this->dataPtr->node.TopicList(allTopics);
for (auto topic : allTopics)
{
std::vector<transport::MessagePublisher> publishers;
this->dataPtr->node.TopicInfo(topic, publishers);
for (auto pub : publishers)
{
if (pub.MsgTypeName() == "ignition.msgs.NavSat")
{
this->dataPtr->topicList.push_back(QString::fromStdString(topic));
break;
}
}
}

// Select first one
if (this->dataPtr->topicList.count() > 0)
this->OnTopic(this->dataPtr->topicList.at(0));
this->TopicListChanged();
}

/////////////////////////////////////////////////
QStringList NavSatMap::TopicList() const
{
return this->dataPtr->topicList;
}

/////////////////////////////////////////////////
void NavSatMap::SetTopicList(const QStringList &_topicList)
{
this->dataPtr->topicList = _topicList;
this->TopicListChanged();
}

// Register this plugin
IGNITION_ADD_PLUGIN(ignition::gui::plugins::NavSatMap,
ignition::gui::Plugin)
106 changes: 106 additions & 0 deletions src/plugins/navsat_map/NavSatMap.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (C) 2021 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef IGNITION_GUI_PLUGINS_IMAGEDISPLAY_HH_
#define IGNITION_GUI_PLUGINS_IMAGEDISPLAY_HH_

#include <memory>
#ifdef _MSC_VER
#pragma warning(push, 0)
#endif
#include <ignition/msgs/navsat.pb.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "ignition/gui/Plugin.hh"

namespace ignition
{
namespace gui
{
namespace plugins
{
class NavSatMapPrivate;

/// \brief Display NavSat messages coming through an Ignition transport topic
/// on top of a map.
///
/// ## Configuration
///
/// \<topic\> : Set the topic to receive NavSat messages.
/// \<topic_picker\> : Whether to show the topic picker, true by default. If
/// this is false, a \<topic\> must be specified.
class NavSatMap : public Plugin
{
Q_OBJECT

/// \brief Topic list
Q_PROPERTY(
QStringList topicList
READ TopicList
WRITE SetTopicList
NOTIFY TopicListChanged
)

/// \brief Constructor
public: NavSatMap();

/// \brief Destructor
public: virtual ~NavSatMap();

// Documentation inherited
public: virtual void LoadConfig(const tinyxml2::XMLElement *_pluginElem);

/// \brief Callback when refresh button is pressed.
public slots: void OnRefresh();

/// \brief Callback when a new topic is chosen on the combo box.
public slots: void OnTopic(const QString _topic);

/// \brief Get the list of topics publishing NavSat messages
/// \return List of topics
public: Q_INVOKABLE QStringList TopicList() const;

/// \brief Set the topic list
/// \param[in] _topicList List of topics
public: Q_INVOKABLE void SetTopicList(const QStringList &_topicList);

/// \brief Notify that topic list has changed
signals: void TopicListChanged();

/// \brief Notify that a new message has been received.
/// \param[in] _latitudeDeg Latitude in degrees
/// \param[in] _longitudeDeg Longitude in degrees
signals: void newMessage(double _latitudeDeg, double _longitudeDeg);

/// \brief Callback in main thread when message changes
private slots: void ProcessMessage();

/// \brief Subscriber callback when new message is received
/// \param[in] _msg New message
private: void OnMessage(const ignition::msgs::NavSat &_msg);

/// \internal
/// \brief Pointer to private data.
private: std::unique_ptr<NavSatMapPrivate> dataPtr;
};
}
}
}

#endif
Loading

0 comments on commit 277f28b

Please sign in to comment.