dsa_only.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 // ##################
19 // #### includes ####
20 // standard includes
21 #include <unistd.h>
22 #include <string>
23 #include <vector>
24 
25 // ROS includes
26 #include <ros/ros.h>
27 
28 // ROS message includes
29 #include <schunk_sdh/TactileSensor.h>
30 #include <schunk_sdh/TactileMatrix.h>
31 
32 // ROS diagnostic msgs
33 #include <diagnostic_msgs/DiagnosticArray.h>
34 #include <diagnostic_msgs/KeyValue.h>
35 
36 #include <schunk_sdh/dsa.h>
37 
38 #include <boost/lexical_cast.hpp>
39 #include <boost/bind.hpp>
40 
41 template<typename T>
42  bool read_vector(ros::NodeHandle &n_, const std::string &key, std::vector<T> & res)
43  {
44  XmlRpc::XmlRpcValue namesXmlRpc;
45  if (!n_.hasParam(key))
46  {
47  return false;
48  }
49 
50  n_.getParam(key, namesXmlRpc);
52  res.resize(namesXmlRpc.size());
53  for (int i = 0; i < namesXmlRpc.size(); i++)
54  {
55  res[i] = (T)namesXmlRpc[i];
56  }
57  return true;
58  }
59 
65 class DsaNode
66 {
67 public:
70 private:
71  // declaration of topics to publish
74 
75  // topic subscribers
76 
77  // service servers
78 
79  // actionlib server
80 
81  // service clients
82  // --
83 
84  // other variables
85  SDH::cDSA *dsa_;
86  SDH::UInt32 last_data_publish_; // time stamp of last data publishing
87 
88  std::string dsadevicestring_;
90  int maxerror_; // maximum error count allowed
91 
94  bool polling_; // try to publish on each response
96  bool use_rle_;
97  bool debug_;
98  double frequency_;
99 
101 
102  std::vector<int> dsa_reorder_;
103 public:
110  nh_("~"), dsa_(0), last_data_publish_(0), isDSAInitialized_(false), error_counter_(0)
111  {
112  topicPub_Diagnostics_ = nh_.advertise < diagnostic_msgs::DiagnosticArray > ("/diagnostics", 1);
113  topicPub_TactileSensor_ = nh_.advertise < schunk_sdh::TactileSensor > ("tactile_data", 1);
114  }
115 
120  {
121  if (isDSAInitialized_)
122  dsa_->Close();
123  if (dsa_)
124  delete dsa_;
125  }
126 
127  void shutdown()
128  {
129  timer_dsa.stop();
130  timer_publish.stop();
131  timer_diag.stop();
132  nh_.shutdown();
133  }
134 
138  bool init()
139  {
140  // implementation of topics to publish
141 
142  nh_.param("dsadevicestring", dsadevicestring_, std::string(""));
143  if (dsadevicestring_.empty())
144  return false;
145 
146  nh_.param("dsadevicenum", dsadevicenum_, 0);
147  nh_.param("maxerror", maxerror_, 8);
148 
149  double publish_frequency, diag_frequency;
150 
151  nh_.param("debug", debug_, false);
152  nh_.param("polling", polling_, false);
153  nh_.param("use_rle", use_rle_, true);
154  nh_.param("diag_frequency", diag_frequency, 5.0);
155  frequency_ = 30.0;
156  if (polling_)
157  nh_.param("poll_frequency", frequency_, 5.0);
158  nh_.param("publish_frequency", publish_frequency, 0.0);
159 
160  auto_publish_ = true;
161 
162  if (polling_)
163  {
164  timer_dsa = nh_.createTimer(ros::Rate(frequency_).expectedCycleTime(), boost::bind(&DsaNode::pollDsa, this));
165  }
166  else
167  {
168  timer_dsa = nh_.createTimer(ros::Rate(frequency_ * 2.0).expectedCycleTime(),
169  boost::bind(&DsaNode::readDsaFrame, this));
170  if (publish_frequency > 0.0)
171  {
172  auto_publish_ = false;
173  timer_publish = nh_.createTimer(ros::Rate(publish_frequency).expectedCycleTime(),
174  boost::bind(&DsaNode::publishTactileData, this));
175  }
176  }
177 
178  timer_diag = nh_.createTimer(ros::Rate(diag_frequency).expectedCycleTime(),
179  boost::bind(&DsaNode::publishDiagnostics, this));
180 
181  if (!read_vector(nh_, "dsa_reorder", dsa_reorder_))
182  {
183  dsa_reorder_.resize(6);
184  dsa_reorder_[0] = 2; // t1
185  dsa_reorder_[1] = 3; // t2
186  dsa_reorder_[2] = 4; // f11
187  dsa_reorder_[3] = 5; // f12
188  dsa_reorder_[4] = 0; // f21
189  dsa_reorder_[5] = 1; // f22
190  }
191 
192  return true;
193  }
194  bool stop()
195  {
196  if (dsa_)
197  {
198  if (isDSAInitialized_)
199  dsa_->Close();
200  delete dsa_;
201  }
202  dsa_ = 0;
203  isDSAInitialized_ = false;
204  return true;
205  }
206 
207  bool start()
208  {
209  if (isDSAInitialized_ == false)
210  {
211  // Init tactile data
212  if (!dsadevicestring_.empty())
213  {
214  try
215  {
216  dsa_ = new SDH::cDSA(0, dsadevicenum_, dsadevicestring_.c_str());
217  if (!polling_)
218  dsa_->SetFramerate(frequency_, use_rle_);
219  else
220  dsa_->SetFramerate(0, use_rle_);
221 
222  ROS_INFO("Initialized RS232 for DSA Tactile Sensors on device %s", dsadevicestring_.c_str());
223  // ROS_INFO("Set sensitivity to 1.0");
224  // for(int i=0; i<6; i++)
225  // dsa_->SetMatrixSensitivity(i, 1.0);
226  error_counter_ = 0;
227  isDSAInitialized_ = true;
228  }
229  catch (SDH::cSDHLibraryException* e)
230  {
231  isDSAInitialized_ = false;
232  ROS_ERROR("An exception was caught: %s", e->what());
233  delete e;
234 
235  shutdown();
236  return false;
237  }
238  }
239  }
240 
241  return true;
242  }
243 
245  {
246  if (debug_)
247  ROS_DEBUG("readDsaFrame");
248 
249  if (isDSAInitialized_)
250  {
251  try
252  {
253  SDH::UInt32 last_time;
254  last_time = dsa_->GetFrame().timestamp;
255  dsa_->UpdateFrame();
256  if (last_time != dsa_->GetFrame().timestamp)
257  {
258  // new data
259  if (error_counter_ > 0)
260  --error_counter_;
261  if (auto_publish_)
263  }
264  }
265  catch (SDH::cSDHLibraryException* e)
266  {
267  ROS_ERROR("An exception was caught: %s", e->what());
268  delete e;
269  ++error_counter_;
270  }
271  if (error_counter_ > maxerror_)
272  stop();
273  }
274  else
275  {
276  start();
277  }
278  }
279 
280  void pollDsa()
281  {
282  if (debug_)
283  ROS_DEBUG("pollDsa");
284 
285  if (isDSAInitialized_)
286  {
287  try
288  {
289  dsa_->SetFramerate(0, use_rle_);
290  readDsaFrame();
291  }
292  catch (SDH::cSDHLibraryException* e)
293  {
294  ROS_ERROR("An exception was caught: %s", e->what());
295  delete e;
296  ++error_counter_;
297  }
298  if (error_counter_ > maxerror_)
299  stop();
300  }
301  else
302  {
303  start();
304  }
305  }
306 
308  {
309  if (debug_)
310  ROS_DEBUG("publishTactileData %ul %ul", dsa_->GetFrame().timestamp, last_data_publish_);
311  if (!isDSAInitialized_ || dsa_->GetFrame().timestamp == last_data_publish_)
312  return; // no new frame available
313  last_data_publish_ = dsa_->GetFrame().timestamp;
314 
315  schunk_sdh::TactileSensor msg;
316  msg.header.stamp = ros::Time::now();
317  int m, x, y;
318  msg.tactile_matrix.resize(dsa_->GetSensorInfo().nb_matrices);
319  ROS_ASSERT(dsa_->GetSensorInfo().nb_matrices == dsa_reorder_.size());
320  for (unsigned int i = 0; i < dsa_reorder_.size(); i++)
321  {
322  m = dsa_reorder_[i];
323  schunk_sdh::TactileMatrix &tm = msg.tactile_matrix[i];
324  tm.matrix_id = i;
325  tm.cells_x = dsa_->GetMatrixInfo(m).cells_x;
326  tm.cells_y = dsa_->GetMatrixInfo(m).cells_y;
327  tm.tactile_array.resize(tm.cells_x * tm.cells_y);
328  for (y = 0; y < tm.cells_y; y++)
329  {
330  for (x = 0; x < tm.cells_x; x++)
331  tm.tactile_array[tm.cells_x * y + x] = dsa_->GetTexel(m, x, y);
332  }
333  }
334  // publish matrix
335  topicPub_TactileSensor_.publish(msg);
336  }
338  {
339  // publishing diagnotic messages
340  diagnostic_msgs::DiagnosticArray diagnostics;
341  diagnostics.status.resize(1);
342  diagnostics.status[0].name = nh_.getNamespace();
343  diagnostics.status[0].values.resize(1);
344  diagnostics.status[0].values[0].key = "error_count";
345  diagnostics.status[0].values[0].value = boost::lexical_cast < std::string > (error_counter_);
346 
347  // set data to diagnostics
348  if (isDSAInitialized_)
349  {
350  diagnostics.status[0].level = 0;
351  diagnostics.status[0].message = "DSA tactile sensing initialized and running";
352  }
353  else if (error_counter_ == 0)
354  {
355  diagnostics.status[0].level = 1;
356  diagnostics.status[0].message = "DSA not initialized";
357  }
358  else
359  {
360  diagnostics.status[0].level = 2;
361  diagnostics.status[0].message = "DSA exceeded eror count";
362  }
363  // publish diagnostic message
364  topicPub_Diagnostics_.publish(diagnostics);
365  if (debug_)
366  ROS_DEBUG_STREAM("publishDiagnostics " << diagnostics);
367  }
368 };
369 // DsaNode
370 
376 int main(int argc, char** argv)
377 {
378  // initialize ROS, spezify name of node
379  ros::init(argc, argv, "schunk_dsa");
380 
381  DsaNode dsa_node;
382 
383  if (!dsa_node.init())
384  return 0;
385 
386  dsa_node.start();
387 
388  ROS_INFO("...dsa node running...");
389 
390  ros::spin();
391 
392  ROS_INFO("...dsa node shut down...");
393  return 0;
394 }
395 
void publish(const boost::shared_ptr< M > &message) const
bool stop()
Definition: dsa_only.cpp:194
~DsaNode()
Destructor for SdhNode class.
Definition: dsa_only.cpp:119
std::string dsadevicestring_
Definition: dsa_only.cpp:88
ros::Publisher topicPub_Diagnostics_
Definition: dsa_only.cpp:73
int size() const
void stop()
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int maxerror_
Definition: dsa_only.cpp:90
int main(int argc, char **argv)
Main loop of ROS node.
Definition: dsa_only.cpp:376
bool init()
Initializes node to get parameters, subscribe and publish to topics.
Definition: dsa_only.cpp:138
void publishDiagnostics()
Definition: dsa_only.cpp:337
ros::NodeHandle nh_
create a handle for this node, initialize node
Definition: dsa_only.cpp:69
DsaNode()
Constructor for SdhNode class.
Definition: dsa_only.cpp:109
bool read_vector(ros::NodeHandle &n_, const std::string &key, std::vector< T > &res)
Definition: dsa_only.cpp:42
void readDsaFrame()
Definition: dsa_only.cpp:244
void pollDsa()
Definition: dsa_only.cpp:280
bool auto_publish_
Definition: dsa_only.cpp:95
int error_counter_
Definition: dsa_only.cpp:93
bool polling_
Definition: dsa_only.cpp:94
SDH::cDSA * dsa_
Definition: dsa_only.cpp:85
double frequency_
Definition: dsa_only.cpp:98
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
bool start()
Definition: dsa_only.cpp:207
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
const std::string & getNamespace() const
ros::Timer timer_diag
Definition: dsa_only.cpp:100
SDH::UInt32 last_data_publish_
Definition: dsa_only.cpp:86
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool isDSAInitialized_
Definition: dsa_only.cpp:92
ROSCPP_DECL void spin()
ros::Timer timer_publish
Definition: dsa_only.cpp:100
#define ROS_DEBUG_STREAM(args)
std::vector< int > dsa_reorder_
Definition: dsa_only.cpp:102
void shutdown()
Definition: dsa_only.cpp:127
ros::Publisher topicPub_TactileSensor_
Definition: dsa_only.cpp:72
bool getParam(const std::string &key, std::string &s) const
Implementation of ROS node for DSA.
Definition: dsa_only.cpp:65
static Time now()
bool debug_
Definition: dsa_only.cpp:97
bool hasParam(const std::string &key) const
#define ROS_ASSERT(cond)
void publishTactileData()
Definition: dsa_only.cpp:307
#define ROS_ERROR(...)
ros::Timer timer_dsa
Definition: dsa_only.cpp:100
bool use_rle_
Definition: dsa_only.cpp:96
#define ROS_DEBUG(...)
int dsadevicenum_
Definition: dsa_only.cpp:89


schunk_sdh
Author(s): Mathias Luedtke , Florian Weisshardt
autogenerated on Mon Nov 25 2019 03:48:23