forked from rock-ros/rtt_ros_transport
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ros_publish_activity.hpp
149 lines (130 loc) · 5.35 KB
/
ros_publish_activity.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/***************************************************************************
tag: Ruben Smits Tue Nov 16 09:18:49 CET 2010 ros_publish_activity.hpp
ros_publish_activity.hpp - description
-------------------
begin : Tue November 16 2010
copyright : (C) 2010 Ruben Smits
email : [email protected]
***************************************************************************
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307 USA *
* *
***************************************************************************/
#ifndef _ROS_MSG_ACTIVITY_HPP_
#define _ROS_MSG_ACTIVITY_HPP_
#include <rtt/Activity.hpp>
#include <rtt/os/Mutex.hpp>
#include <rtt/os/MutexLock.hpp>
#include <boost/shared_ptr.hpp>
#include <rtt/Logger.hpp>
#include <ros/ros.h>
namespace RTT{
namespace ros{
/**
* The interface a channel element must implement in
* order to publish data to a ROS topic.
*/
struct RosPublisher
{
public:
/**
* Publish all data in the channel to a ROS topic.
*/
virtual void publish()=0;
};
/**
* A process wide thread that handles all publishing of
* ROS topics of the current process.
* There is no strong reason why only one publisher should
* exist, in later implementations, one publisher thread per
* channel may exist as well. See the usage recommendations
* for Instance()
*/
class RosPublishActivity : public RTT::Activity {
public:
typedef boost::shared_ptr<RosPublishActivity> shared_ptr;
private:
typedef boost::weak_ptr<RosPublishActivity> weak_ptr;
//! This pointer may not be refcounted since it would prevent cleanup.
static weak_ptr ros_pub_act;
//! A map keeping track of all publishers in the current
//! process. It must be guarded by the mutex since
//! insertion/removal happens concurrently.
typedef std::map< RosPublisher*, bool> Publishers;
Publishers publishers;
os::Mutex map_lock;
RosPublishActivity( const std::string& name)
: Activity(ORO_SCHED_OTHER, RTT::os::LowestPriority, 0.0, 0, name)
{
Logger::In in("RosPublishActivity");
log(Debug)<<"Creating RosPublishActivity"<<endlog();
}
void loop(){
os::MutexLock lock(map_lock);
for(Publishers::iterator it = publishers.begin(); it != publishers.end(); ++it)
if (it->second) {
it->second = false; // protected by the mutex lock !
it->first->publish();
}
}
public:
/**
* Returns the single instance of the RosPublisher. This function
* is not thread-safe when it creates the RosPublisher object.
* Therefor, it is advised to cache the object which Intance() returns
* such that, in the unlikely event that two publishers exist,
* you consistently keep using the same instance, which is fine then.
*/
static shared_ptr Instance() {
shared_ptr ret = ros_pub_act.lock();
if ( !ret ) {
ret.reset(new RosPublishActivity("RosPublishActivity"));
ros_pub_act = ret;
ret->start();
}
return ret;
}
void addPublisher(RosPublisher* pub) {
os::MutexLock lock(map_lock);
publishers[pub] = false;
}
void removePublisher(RosPublisher* pub) {
os::MutexLock lock(map_lock);
publishers.erase(pub);
}
/**
* Requests to publish the data of a given channel.
* Note that multiple calls to requestPublish may
* cause only a single call to RosPublisher::publish().
*/
bool requestPublish(RosPublisher* chan){
// flag that data is available in a channel:
{
os::MutexLock lock(map_lock);
assert(publishers.find(chan) != publishers.end() );
publishers.find(chan)->second = true;
}
// trigger loop()
this->trigger();
return true;
}
~RosPublishActivity() {
Logger::In in("RosPublishActivity");
log(Info) << "RosPublishActivity cleans up: no more work."<<endlog();
stop();
}
};//class
}}//namespace
#endif