Commit 591ba07e authored by Valentin Platzgummer's avatar Valentin Platzgummer

123

parent e089277b
...@@ -28,11 +28,12 @@ QGCROOT = $$PWD ...@@ -28,11 +28,12 @@ QGCROOT = $$PWD
DebugBuild { DebugBuild {
DESTDIR = $${OUT_PWD}/debug DESTDIR = $${OUT_PWD}/debug
DEFINES += DEBUG DEFINES += DEBUG
DEFINES += ROS_BRIDGE_DEBUG
#DEFINES += ROS_BRIDGE_CLIENT_DEBUG #DEFINES += ROS_BRIDGE_CLIENT_DEBUG
} }
else { else {
DESTDIR = $${OUT_PWD}/release DESTDIR = $${OUT_PWD}/release
DEFINES += DEBUG DEFINES += ROS_BRIDGE_DEBUG
DEFINES += NDEBUG DEFINES += NDEBUG
} }
......
...@@ -13,6 +13,9 @@ public: ...@@ -13,6 +13,9 @@ public:
WimaPolygonArray(const WimaPolygonArray &other) : WimaPolygonArray(const WimaPolygonArray &other) :
_polygons(other._polygons), _dirty(true) _polygons(other._polygons), _dirty(true)
{} {}
~WimaPolygonArray(){
_objs.clearAndDeleteContents();
}
class QmlObjectListModel *QmlObjectListModel(){ class QmlObjectListModel *QmlObjectListModel(){
if (_dirty) if (_dirty)
...@@ -34,9 +37,9 @@ public: ...@@ -34,9 +37,9 @@ public:
private: private:
void _updateObjects(void){ void _updateObjects(void){
_objs.clear(); _objs.clearAndDeleteContents();
for (long i=0; i<_polygons.size(); ++i){ for (long i=0; i<_polygons.size(); ++i){
_objs.append(&_polygons[i]); _objs.append(new PolygonType(_polygons[i]));
} }
} }
......
...@@ -89,6 +89,7 @@ WimaController::WimaController(QObject *parent) ...@@ -89,6 +89,7 @@ WimaController::WimaController(QObject *parent)
, _batteryLevelTicker (EVENT_TIMER_INTERVAL, 1000 /*ms*/) , _batteryLevelTicker (EVENT_TIMER_INTERVAL, 1000 /*ms*/)
, _snakeTicker (EVENT_TIMER_INTERVAL, 200 /*ms*/) , _snakeTicker (EVENT_TIMER_INTERVAL, 200 /*ms*/)
, _nemoTimeoutTicker (EVENT_TIMER_INTERVAL, 5000 /*ms*/) , _nemoTimeoutTicker (EVENT_TIMER_INTERVAL, 5000 /*ms*/)
, _topicServiceSetupDone (false)
{ {
// ROS Bridge. // ROS Bridge.
...@@ -552,22 +553,28 @@ bool WimaController::setWimaPlanData(const WimaPlanData &planData) ...@@ -552,22 +553,28 @@ bool WimaController::setWimaPlanData(const WimaPlanData &planData)
if ( _enableSnake.rawValue().toBool() if ( _enableSnake.rawValue().toBool()
&& _pRosBridge->isRunning() && _pRosBridge->isRunning()
&& _pRosBridge->connected() ){ && _pRosBridge->connected()
if ( _snakeTilesLocal.polygons().size() > 0 ){ && _topicServiceSetupDone
&& _snakeTilesLocal.polygons().size() > 0
)
{
using namespace ros_bridge::messages; using namespace ros_bridge::messages;
// Publish snake origin. // Publish snake origin.
JsonDocUPtr jOrigin(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr jOrigin(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
Q_ASSERT(geographic_msgs::geo_point::toJson( bool ret = geographic_msgs::geo_point::toJson(
_snakeOrigin, *jOrigin, jOrigin->GetAllocator())); _snakeOrigin, *jOrigin, jOrigin->GetAllocator());
Q_ASSERT(ret);
_pRosBridge->publish(std::move(jOrigin), "/snake/origin"); _pRosBridge->publish(std::move(jOrigin), "/snake/origin");
// Publish snake tiles. // Publish snake tiles.
JsonDocUPtr jSnakeTiles(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr jSnakeTiles(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
Q_ASSERT(jsk_recognition_msgs::polygon_array::toJson( ret = jsk_recognition_msgs::polygon_array::toJson(
_snakeTilesLocal, *jSnakeTiles, jSnakeTiles->GetAllocator())); _snakeTilesLocal, *jSnakeTiles, jSnakeTiles->GetAllocator());
Q_ASSERT(ret);
_pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles"); _pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles");
}
} }
_localPlanDataValid = true; _localPlanDataValid = true;
return true; return true;
} }
...@@ -758,21 +765,24 @@ void WimaController::_eventTimerHandler() ...@@ -758,21 +765,24 @@ void WimaController::_eventTimerHandler()
} }
if ( _snakeTicker.ready() ) { if ( _snakeTicker.ready() ) {
static bool setupDone = false;
if ( _enableSnake.rawValue().toBool() ) { if ( _enableSnake.rawValue().toBool() ) {
if ( !_pRosBridge->isRunning()) { if ( !_pRosBridge->isRunning()) {
_pRosBridge->start(); _pRosBridge->start();
} else if ( _pRosBridge->isRunning() && _pRosBridge->connected() && !setupDone) { } else if ( _pRosBridge->isRunning()
&& _pRosBridge->connected()
&& !_topicServiceSetupDone) {
if ( _doTopicServiceSetup() )
_topicServiceSetupDone = true;
} else if ( _pRosBridge->isRunning()
&& !_pRosBridge->connected()
&& _topicServiceSetupDone){
_pRosBridge->reset(); _pRosBridge->reset();
_pRosBridge->start(); _pRosBridge->start();
_setupTopicService(); _topicServiceSetupDone = false;
setupDone = true;
} else if ( _pRosBridge->isRunning() && !_pRosBridge->connected() ){
setupDone = false;
} }
} else if ( _pRosBridge->isRunning() ) { } else if ( _pRosBridge->isRunning() ) {
_pRosBridge->reset(); _pRosBridge->reset();
setupDone = false; _topicServiceSetupDone = false;
} }
} }
} }
...@@ -948,21 +958,35 @@ void WimaController::_switchSnakeManager(QVariant variant) ...@@ -948,21 +958,35 @@ void WimaController::_switchSnakeManager(QVariant variant)
} }
} }
void WimaController::_setupTopicService() bool WimaController::_doTopicServiceSetup()
{ {
using namespace ros_bridge::messages; using namespace ros_bridge::messages;
if ( _snakeTilesLocal.polygons().size() > 0){
if ( _snakeTilesLocal.polygons().size() == 0)
return false;
// Publish snake origin. // Publish snake origin.
_pRosBridge->advertiseTopic("/snake/origin",
geographic_msgs::geo_point::messageType().c_str());
JsonDocUPtr jOrigin(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr jOrigin(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
Q_ASSERT(geographic_msgs::geo_point::toJson( bool ret = geographic_msgs::geo_point::toJson(
_snakeOrigin, *jOrigin, jOrigin->GetAllocator())); _snakeOrigin, *jOrigin.get(), jOrigin->GetAllocator());
Q_ASSERT(ret);
(void)ret;
_pRosBridge->publish(std::move(jOrigin), "/snake/origin"); _pRosBridge->publish(std::move(jOrigin), "/snake/origin");
// Publish snake tiles. // Publish snake tiles.
_pRosBridge->advertiseTopic("/snake/tiles",
jsk_recognition_msgs::polygon_array::messageType().c_str());
JsonDocUPtr jSnakeTiles(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr jSnakeTiles(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
Q_ASSERT(jsk_recognition_msgs::polygon_array::toJson( ret = jsk_recognition_msgs::polygon_array::toJson(
_snakeTilesLocal, *jSnakeTiles, jSnakeTiles->GetAllocator())); _snakeTilesLocal, *jSnakeTiles, jSnakeTiles->GetAllocator());
Q_ASSERT(ret);
(void)ret;
_pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles"); _pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles");
}
// Subscribe nemo progress. // Subscribe nemo progress.
_pRosBridge->subscribe("/nemo/progress", _pRosBridge->subscribe("/nemo/progress",
/* callback */ [this](JsonDocUPtr pDoc){ /* callback */ [this](JsonDocUPtr pDoc){
...@@ -972,23 +996,29 @@ void WimaController::_setupTopicService() ...@@ -972,23 +996,29 @@ void WimaController::_setupTopicService()
|| progress_msg.progress().size() != requiredSize ) { // Some error occured. || progress_msg.progress().size() != requiredSize ) { // Some error occured.
// Set progress to default. // Set progress to default.
progress_msg.progress().fill(0, requiredSize); progress_msg.progress().fill(0, requiredSize);
// Publish origin and tiles again, if valid.
if ( this->_snakeTilesLocal.polygons().size() > 0){
// Publish snake origin. // Publish snake origin.
JsonDocUPtr jOrigin(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr jOrigin(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
Q_ASSERT(geographic_msgs::geo_point::toJson( bool ret = geographic_msgs::geo_point::toJson(
this->_snakeOrigin, *jOrigin, jOrigin->GetAllocator())); this->_snakeOrigin, *jOrigin, jOrigin->GetAllocator());
Q_ASSERT(ret);
(void)ret;
this->_pRosBridge->publish(std::move(jOrigin), "/snake/origin"); this->_pRosBridge->publish(std::move(jOrigin), "/snake/origin");
// Publish snake tiles. // Publish snake tiles.
JsonDocUPtr jSnakeTiles(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr jSnakeTiles(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
Q_ASSERT(jsk_recognition_msgs::polygon_array::toJson( ret = jsk_recognition_msgs::polygon_array::toJson(
this->_snakeTilesLocal, *jSnakeTiles, jSnakeTiles->GetAllocator())); this->_snakeTilesLocal, *jSnakeTiles, jSnakeTiles->GetAllocator());
Q_ASSERT(ret);
(void)ret;
this->_pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles"); this->_pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles");
} }
}
emit WimaController::nemoProgressChanged(); emit WimaController::nemoProgressChanged();
}); });
// Subscribe /nemo/heartbeat.
_pRosBridge->subscribe("/nemo/heartbeat", _pRosBridge->subscribe("/nemo/heartbeat",
/* callback */ [this](JsonDocUPtr pDoc){ /* callback */ [this](JsonDocUPtr pDoc){
auto &heartbeat_msg = this->_nemoHeartbeat; auto &heartbeat_msg = this->_nemoHeartbeat;
...@@ -1004,31 +1034,38 @@ void WimaController::_setupTopicService() ...@@ -1004,31 +1034,38 @@ void WimaController::_setupTopicService()
emit WimaController::nemoStatusStringChanged(); emit WimaController::nemoStatusStringChanged();
}); });
// Advertise /snake/get_origin.
_pRosBridge->advertiseService("/snake/get_origin", "snake_msgs/GetOrigin", _pRosBridge->advertiseService("/snake/get_origin", "snake_msgs/GetOrigin",
[this](JsonDocUPtr) -> JsonDocUPtr [this](JsonDocUPtr) -> JsonDocUPtr
{ {
using namespace ros_bridge::messages; using namespace ros_bridge::messages;
JsonDocUPtr pDoc(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr pDoc(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
::GeoPoint3D origin = this->_snakeOrigin;
rapidjson::Value jOrigin(rapidjson::kObjectType); rapidjson::Value jOrigin(rapidjson::kObjectType);
if ( this->_snakeTilesLocal.polygons().size() > 0){ bool ret = geographic_msgs::geo_point::toJson(
geographic_msgs::geo_point::toJson( origin, jOrigin, pDoc->GetAllocator());
this->_snakeOrigin, jOrigin, pDoc->GetAllocator()); Q_ASSERT(ret);
} else { (void)ret;
geographic_msgs::geo_point::toJson(
::GeoPoint3D(0,0,0), jOrigin, pDoc->GetAllocator());
}
pDoc->AddMember("origin", jOrigin, pDoc->GetAllocator()); pDoc->AddMember("origin", jOrigin, pDoc->GetAllocator());
return pDoc; return pDoc;
}); });
// Advertise /snake/get_tiles.
_pRosBridge->advertiseService("/snake/get_tiles", "snake_msgs/GetTiles", _pRosBridge->advertiseService("/snake/get_tiles", "snake_msgs/GetTiles",
[this](JsonDocUPtr) -> JsonDocUPtr [this](JsonDocUPtr) -> JsonDocUPtr
{ {
JsonDocUPtr pDoc(std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); JsonDocUPtr pDoc(std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
rapidjson::Value jSnakeTiles(rapidjson::kObjectType); rapidjson::Value jSnakeTiles(rapidjson::kObjectType);
jsk_recognition_msgs::polygon_array::toJson( bool ret = jsk_recognition_msgs::polygon_array::toJson(
this->_snakeTilesLocal, jSnakeTiles, pDoc->GetAllocator()); this->_snakeTilesLocal, jSnakeTiles, pDoc->GetAllocator());
Q_ASSERT(ret);
(void)ret;
pDoc->AddMember("tiles", jSnakeTiles, pDoc->GetAllocator()); pDoc->AddMember("tiles", jSnakeTiles, pDoc->GetAllocator());
return pDoc; return pDoc;
}); });
return true;
} }
...@@ -337,7 +337,7 @@ private slots: ...@@ -337,7 +337,7 @@ private slots:
void _snakeStoreWorkerResults (); void _snakeStoreWorkerResults ();
void _initStartSnakeWorker (); void _initStartSnakeWorker ();
void _switchSnakeManager (QVariant variant); void _switchSnakeManager (QVariant variant);
void _setupTopicService (); bool _doTopicServiceSetup();
// Periodic tasks. // Periodic tasks.
void _eventTimerHandler (void); void _eventTimerHandler (void);
// Waypoint manager handling. // Waypoint manager handling.
...@@ -407,6 +407,7 @@ private: ...@@ -407,6 +407,7 @@ private:
int _fallbackStatus; int _fallbackStatus;
ROSBridgePtr _pRosBridge; ROSBridgePtr _pRosBridge;
static StatusMap _nemoStatusMap; static StatusMap _nemoStatusMap;
bool _topicServiceSetupDone;
// Periodic tasks. // Periodic tasks.
QTimer _eventTimer; QTimer _eventTimer;
......
This diff is collapsed.
This diff is collapsed.
...@@ -20,18 +20,10 @@ bool ros_bridge::com_private::getTopic(const ros_bridge::com_private::JsonDoc &d ...@@ -20,18 +20,10 @@ bool ros_bridge::com_private::getTopic(const ros_bridge::com_private::JsonDoc &d
{ {
if ( doc.HasMember("topic") && doc["topic"].IsString() ){ if ( doc.HasMember("topic") && doc["topic"].IsString() ){
rapidjson::StringBuffer sb1;
rapidjson::Writer<rapidjson::StringBuffer> writer1(sb1);
doc.Accept(writer1);
std::cout << "getTopic doc: " << sb1.GetString() << std::endl;
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
doc["topic"].Accept(writer); doc["topic"].Accept(writer);
topic = sb.GetString(); topic = sb.GetString();
std::cout << "getTopic topic: " << sb.GetString() << std::endl;
return true; return true;
} else } else
return false; return false;
......
#include "geopoint.h" #include "geopoint.h"
std::string ros_bridge::messages::geographic_msgs::geo_point::messageType(){ std::string ros_bridge::messages::geographic_msgs::geo_point::messageType(){
return "geometry_msgs/GeoPoint"; return "geographic_msgs/GeoPoint";
} }
...@@ -109,9 +109,6 @@ bool toJson(const T&p, rapidjson::Value &value, rapidjson::Document::AllocatorTy ...@@ -109,9 +109,6 @@ bool toJson(const T&p, rapidjson::Value &value, rapidjson::Document::AllocatorTy
auto altitude = detail::getAltitude(p, traits::Type2Type<Components>()); // If T has no member altitude() replace it by 0.0; auto altitude = detail::getAltitude(p, traits::Type2Type<Components>()); // If T has no member altitude() replace it by 0.0;
value.AddMember("altitude", rapidjson::Value().SetFloat((_Float64)altitude), allocator); value.AddMember("altitude", rapidjson::Value().SetFloat((_Float64)altitude), allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -103,9 +103,6 @@ bool toJson(const T&p, rapidjson::Value &value, rapidjson::Document::AllocatorTy ...@@ -103,9 +103,6 @@ bool toJson(const T&p, rapidjson::Value &value, rapidjson::Document::AllocatorTy
auto z = detail::getZ(p, Type2Type<Components>()); // If T has no member z() replace it by 0. auto z = detail::getZ(p, Type2Type<Components>()); // If T has no member z() replace it by 0.
value.AddMember("z", rapidjson::Value().SetFloat(z), allocator); value.AddMember("z", rapidjson::Value().SetFloat(z), allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -57,9 +57,6 @@ bool toJson(const PolygonType &poly, rapidjson::Value &value, rapidjson::Documen ...@@ -57,9 +57,6 @@ bool toJson(const PolygonType &poly, rapidjson::Value &value, rapidjson::Documen
} }
value.AddMember("points", points, allocator); value.AddMember("points", points, allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -95,9 +95,6 @@ bool _toJson(const PolygonType &poly, ...@@ -95,9 +95,6 @@ bool _toJson(const PolygonType &poly,
} }
value.AddMember("header", header, allocator); value.AddMember("header", header, allocator);
value.AddMember("polygon", polygon, allocator); value.AddMember("polygon", polygon, allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -183,10 +183,6 @@ namespace detail { ...@@ -183,10 +183,6 @@ namespace detail {
detail::likelihoodToJson(p, jLikelihood, allocator, traits::Int2Type<HasLikelihood::value>()); detail::likelihoodToJson(p, jLikelihood, allocator, traits::Int2Type<HasLikelihood::value>());
value.AddMember("likelihood", jLikelihood, allocator); value.AddMember("likelihood", jLikelihood, allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -32,9 +32,6 @@ template <class HeartbeatType> ...@@ -32,9 +32,6 @@ template <class HeartbeatType>
bool toJson(const HeartbeatType &heartbeat, rapidjson::Value &value, rapidjson::Document::AllocatorType &allocator) bool toJson(const HeartbeatType &heartbeat, rapidjson::Value &value, rapidjson::Document::AllocatorType &allocator)
{ {
value.AddMember("status", std::int32_t(heartbeat.status()), allocator); value.AddMember("status", std::int32_t(heartbeat.status()), allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -41,9 +41,6 @@ bool toJson(const ProgressType &p, rapidjson::Value &value, rapidjson::Document: ...@@ -41,9 +41,6 @@ bool toJson(const ProgressType &p, rapidjson::Value &value, rapidjson::Document:
jProgress.PushBack(rapidjson::Value().SetInt(std::int32_t(p.progress()[i])), allocator); jProgress.PushBack(rapidjson::Value().SetInt(std::int32_t(p.progress()[i])), allocator);
} }
value.AddMember("progress", jProgress, allocator); value.AddMember("progress", jProgress, allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -62,9 +62,6 @@ bool toJson(const HeaderType &header, ...@@ -62,9 +62,6 @@ bool toJson(const HeaderType &header,
header.frameId().length(), header.frameId().length(),
allocator), allocator),
allocator); allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -37,9 +37,6 @@ bool toJson(const TimeType &time, ...@@ -37,9 +37,6 @@ bool toJson(const TimeType &time,
{ {
value.AddMember("secs", rapidjson::Value().SetUint(uint32_t(time.secs())), allocator); value.AddMember("secs", rapidjson::Value().SetUint(uint32_t(time.secs())), allocator);
value.AddMember("nsecs", rapidjson::Value().SetUint(uint32_t(time.nSecs())), allocator); value.AddMember("nsecs", rapidjson::Value().SetUint(uint32_t(time.nSecs())), allocator);
rapidjson::Value jType;
jType.SetString(messageType().c_str(), allocator);
value.AddMember("type", jType, allocator);
return true; return true;
} }
......
...@@ -23,13 +23,16 @@ public: ...@@ -23,13 +23,16 @@ public:
void advertiseService(const char* service, void advertiseService(const char* service,
const char* type, const char* type,
const std::function<JsonDocUPtr(JsonDocUPtr)> &callback); const std::function<JsonDocUPtr(JsonDocUPtr)> &callback);
void advertiseTopic(const char* topic,
const char* type);
//! @brief Start ROS bridge. //! @brief Start ROS bridge.
void start(); void start();
//! @brief Stops ROS bridge. //! @brief Stops ROS bridge.
void reset(); void reset();
//! @return Returns true if connected to the rosbridge_server, false either. //! @return Returns true if connected to the rosbridge_server, false either.
//! @note This function can block up to 100ms. However normal execution time is smaller. //! @note \fn calls start().
bool connected(); bool connected();
bool isRunning(); bool isRunning();
......
...@@ -20,8 +20,6 @@ void ros_bridge::com_private::TopicPublisher::start() ...@@ -20,8 +20,6 @@ void ros_bridge::com_private::TopicPublisher::start()
return; return;
_stopped->store(false); _stopped->store(false);
_pThread = std::make_unique<std::thread>([this]{ _pThread = std::make_unique<std::thread>([this]{
// Init.
std::unordered_map<std::string, std::string> topicMap;
// Main Loop. // Main Loop.
while( !this->_stopped->load() ){ while( !this->_stopped->load() ){
std::unique_lock<std::mutex> lk(this->_mutex); std::unique_lock<std::mutex> lk(this->_mutex);
...@@ -39,38 +37,25 @@ void ros_bridge::com_private::TopicPublisher::start() ...@@ -39,38 +37,25 @@ void ros_bridge::com_private::TopicPublisher::start()
// Get topic and type from Json message and remove it. // Get topic and type from Json message and remove it.
std::string topic; std::string topic;
assert(com_private::getTopic(*pJsonDoc, topic)); bool ret = com_private::getTopic(*pJsonDoc, topic);
assert(com_private::removeTopic(*pJsonDoc)); assert(ret);
std::string type; (void)ret;
assert(com_private::getType(*pJsonDoc, type)); ret = com_private::removeTopic(*pJsonDoc);
assert(com_private::removeType(*pJsonDoc)); assert(ret);
(void)ret;
// Check if topic must be advertised. // Wait for topic (Rosbridge needs some time to process a advertise() request).
std::string clientName =
ros_bridge::com_private::_topicAdvertiserKey
+ topic;
auto it = topicMap.find(clientName);
if ( it == topicMap.end()) { // Need to advertise topic?
topicMap.insert(std::make_pair(clientName, topic));
this->_rbc.addClient(clientName);
this->_rbc.advertise(clientName, topic, type);
this->_rbc.waitForTopic(topic, [this]{ this->_rbc.waitForTopic(topic, [this]{
return this->_stopped->load(); return this->_stopped->load();
}); // Wait until topic is advertised. });
}
// Publish Json message. // Publish Json message.
if ( !this->_stopped->load() ) if ( !this->_stopped->load() )
this->_rbc.publish(topic, *pJsonDoc); this->_rbc.publish(topic, *pJsonDoc);
} // while loop } // while loop
#ifdef ROS_BRIDGE_DEBUG
// Tidy up.
for (auto& it : topicMap){
this->_rbc.unadvertise(it.second);
this->_rbc.removeClient(it.first);
}
std::cout << "TopicPublisher: publisher thread terminated." << std::endl; std::cout << "TopicPublisher: publisher thread terminated." << std::endl;
#endif
}); });
} }
...@@ -88,6 +73,12 @@ void ros_bridge::com_private::TopicPublisher::reset() ...@@ -88,6 +73,12 @@ void ros_bridge::com_private::TopicPublisher::reset()
_pThread->join(); _pThread->join();
lk.lock(); lk.lock();
// Tidy up.
for (auto& it : this->_topicMap){
this->_rbc.unadvertise(it.first);
this->_rbc.removeClient(it.second);
}
this->_topicMap.clear();
_queue.clear(); _queue.clear();
} }
...@@ -95,14 +86,52 @@ void ros_bridge::com_private::TopicPublisher::publish( ...@@ -95,14 +86,52 @@ void ros_bridge::com_private::TopicPublisher::publish(
ros_bridge::com_private::JsonDocUPtr docPtr, ros_bridge::com_private::JsonDocUPtr docPtr,
const char *topic) const char *topic)
{ {
std::cout << "TopicPublisher \"topic\": " << topic << std::endl; // Check if topic was advertised.
std::string t(topic);
std::unique_lock<std::mutex> lk(this->_mutex);
auto it = this->_topicMap.find(t);
if ( it == this->_topicMap.end()) { // Not yet advertised?
lk.unlock();
#ifdef ROS_BRIDGE_DEBUG
std::cerr << "TopicPublisher: topic "
<< t << " not yet advertised" << std::endl;
#endif
return;
}
lk.unlock();
// Add topic information to json doc.
auto &allocator = docPtr->GetAllocator(); auto &allocator = docPtr->GetAllocator();
rapidjson::Value key("topic", allocator); rapidjson::Value key("topic", allocator);
rapidjson::Value value(topic, allocator); rapidjson::Value value(topic, allocator);
docPtr->AddMember(key, value, allocator); docPtr->AddMember(key, value, allocator);
std::unique_lock<std::mutex> lock(_mutex);
lk.lock();
_queue.push_back(std::move(docPtr)); _queue.push_back(std::move(docPtr));
lock.unlock(); lk.unlock();
_cv.notify_one(); // Wake publisher thread. _cv.notify_one(); // Wake publisher thread.
} }
bool ros_bridge::com_private::TopicPublisher::advertise(const char *topic, const char *type)
{
std::unique_lock<std::mutex> lk(this->_mutex);
std::string t(topic);
auto it = this->_topicMap.find(t);
if ( it == this->_topicMap.end()) { // Need to advertise topic?
std::string clientName =
std::string(ros_bridge::com_private::_topicAdvertiserKey)
+ t;
this->_topicMap.insert(std::make_pair(t, clientName));
lk.unlock();
this->_rbc.addClient(clientName);
this->_rbc.advertise(clientName, t, type);
return true;
} else {
lk.unlock();
#if ROS_BRIDGE_DEBUG
std::cerr << "TopicPublisher: topic " << topic << " already advertised" << std::endl;
#endif
return false;
}
}
...@@ -31,9 +31,12 @@ public: ...@@ -31,9 +31,12 @@ public:
void reset(); void reset();
void publish(JsonDocUPtr docPtr, const char *topic); void publish(JsonDocUPtr docPtr, const char *topic);
bool advertise(const char *topic, const char *type);
private: private:
using TopicMap = std::unordered_map<std::string, std::string>;
JsonQueue _queue; JsonQueue _queue;
TopicMap _topicMap;
std::mutex _mutex; std::mutex _mutex;
std::shared_ptr<std::atomic_bool> _stopped; std::shared_ptr<std::atomic_bool> _stopped;
RosbridgeWsClient &_rbc; RosbridgeWsClient &_rbc;
......
...@@ -32,8 +32,15 @@ void ros_bridge::ROSBridge::advertiseService(const char *service, ...@@ -32,8 +32,15 @@ void ros_bridge::ROSBridge::advertiseService(const char *service,
_server.advertiseService(service, type, callback); _server.advertiseService(service, type, callback);
} }
void ros_bridge::ROSBridge::advertiseTopic(const char *topic, const char *type)
{
_topicPublisher.advertise(topic, type);
}
void ros_bridge::ROSBridge::start() void ros_bridge::ROSBridge::start()
{ {
if ( !_stopped->load() )
return;
_stopped->store(false); _stopped->store(false);
_rbc.run(); _rbc.run();
_topicPublisher.start(); _topicPublisher.start();
...@@ -44,6 +51,8 @@ void ros_bridge::ROSBridge::start() ...@@ -44,6 +51,8 @@ void ros_bridge::ROSBridge::start()
void ros_bridge::ROSBridge::reset() void ros_bridge::ROSBridge::reset()
{ {
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
if ( _stopped->load() )
return;
_stopped->store(true); _stopped->store(true);
_topicPublisher.reset(); _topicPublisher.reset();
_topicSubscriber.reset(); _topicSubscriber.reset();
...@@ -56,6 +65,7 @@ void ros_bridge::ROSBridge::reset() ...@@ -56,6 +65,7 @@ void ros_bridge::ROSBridge::reset()
bool ros_bridge::ROSBridge::connected() bool ros_bridge::ROSBridge::connected()
{ {
start();
return _rbc.connected(); return _rbc.connected();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment