dsp3000_node.cpp
Go to the documentation of this file.
1 
37 #include <math.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <sstream>
42 #include <string>
43 #include <tuple>
44 #include <vector>
45 #include "kvh/dsp3000_mode.h"
46 #include "kvh/dsp3000_parser.h"
47 #include "kvh/serial_port.h"
48 #include "ros/ros.h"
49 #include "std_msgs/Float32.h"
50 
51 static constexpr int TIMEOUT = 1000;
52 static constexpr float PI = 3.14159265359f;
53 
54 using std::string;
55 using std::stringstream;
56 using std::vector;
57 using std::tuple;
58 using std::get;
59 
61 tuple<string, string> get_mode_data(KvhDsp3000Mode mode);
62 
63 bool configure_dsp3000(SerialPort *device, KvhDsp3000Mode mode);
64 
65 string get_mode_topic_name(KvhDsp3000Mode const mode);
66 
67 tuple<string, string> get_mode_data(KvhDsp3000Mode const mode)
68 {
69  tuple<string, string> output;
70  switch (mode)
71  {
72  case KVH_DSP3000_RATE:
73  get<0>(output) = "RRR";
74  get<1>(output) = "rate";
75  break;
77  get<0>(output) = "AAA";
78  get<1>(output) = "incremental angle";
79  break;
81  get<0>(output) = "PPP";
82  get<1>(output) = "integrated angle";
83  break;
84  default:
85  assert(!"mode not understood");
86  }
87  return output;
88 }
89 
91 {
92  string output;
93  switch (mode)
94  {
95  case KVH_DSP3000_RATE:
96  output = "rate";
97  break;
99  output = "incremental_angle";
100  break;
102  output = "integrated_angle";
103  break;
104  default:
105  assert(!"mode not understood");
106  }
107  return output;
108 }
109 
110 bool configure_dsp3000(SerialPort *const device, KvhDsp3000Mode const mode)
111 {
112  bool output = true;
113 
114  ROS_INFO("Zeroing the DSP-3000.");
115  try
116  {
117  // Start by zeroing the sensor. Write three times, to ensure it is received
118  device->write("ZZZ", 3);
119  }
120  catch (SerialTimeoutException &e)
121  {
122  ROS_ERROR("Unable to communicate with DSP-3000 device.");
123  output = false;
124  }
125 
126  if (output)
127  {
128  tuple<string, string> mode_data(get_mode_data(mode));
129  ROS_INFO("Configuring for %s output.", get<1>(mode_data).c_str());
130  try
131  {
132  device->write(get<0>(mode_data).c_str(), static_cast<int>(get<0>(mode_data).size()));
133  }
134  catch (SerialTimeoutException &e)
135  {
136  ROS_ERROR("Unable to communicate with DSP-3000 device.");
137  }
138  }
139 
140  return output;
141 }
142 
143 int main(int argc, char **argv)
144 {
145  ros::init(argc, argv, "dsp3000");
146 
147  string port_name;
148  ros::param::param<std::string>("~port", port_name, "/dev/ttyUSB0");
149  int32_t mode;
150  ros::param::param<int32_t>("~mode", mode, KVH_DSP3000_RATE);
152  {
153  ROS_ERROR("bad mode: %d", mode);
154  return EXIT_FAILURE;
155  }
156  bool invert = false;
157  ros::param::param<bool>("~invert", invert, invert);
158 
159  // Define the publisher topic name
160  ros::NodeHandle n;
161  ros::Publisher dsp3000_pub =
162  n.advertise<std_msgs::Float32>("dsp3000_" + get_mode_topic_name(static_cast<KvhDsp3000Mode>(mode)), 100);
163 
164  SerialPort device;
165 
166  try
167  {
168  device.open(port_name.c_str(), 38400);
169  }
170  catch (SerialException &e)
171  {
172  ROS_FATAL("%s", e.what());
173  return EXIT_FAILURE;
174  }
175  ROS_INFO("The serial port named \"%s\" is opened.", port_name.c_str());
176 
177  configure_dsp3000(&device, static_cast<KvhDsp3000Mode>(mode));
178  char temp_buffer[128];
179  bool user_notified_of_timeout = false;
180  int previous_errno = 0;
181  bool ignoring_buffer_overflow = true;
182  int temp_buffer_length = 0;
183  uint8_t temporary_buffer_ignore_limit = 0U;
184  bool streaming_data = false;
185  while (ros::ok())
186  {
187  // Get the reply, the last value is the timeout in ms
188  try
189  {
190  // Subtract 1 from sizeof(temp_buffer) because we will manually null terminate later
191  int const new_bytes =
192  device.readLine(&temp_buffer[temp_buffer_length], sizeof(temp_buffer) - temp_buffer_length - 1, TIMEOUT);
193  temp_buffer_length += new_bytes;
194  ignoring_buffer_overflow = false;
195  }
196  catch (SerialTimeoutException &e)
197  {
198  if (!user_notified_of_timeout)
199  {
200  ROS_ERROR("Timed out while talking with DSP-3000 device.");
201  user_notified_of_timeout = true;
202  }
203  continue;
204  }
205  catch (SerialBufferFilledException &e)
206  {
207  if (!ignoring_buffer_overflow)
208  {
209  ROS_ERROR("%s", e.what());
210  }
211  temp_buffer_length = sizeof(temp_buffer) - 1;
212  }
213  catch (SerialException &e)
214  {
215  int32_t constexpr INTERRUPTED_SYSTEM_CALL_ERRNO = 4;
216  if (INTERRUPTED_SYSTEM_CALL_ERRNO != errno && previous_errno != errno)
217  {
218  ROS_ERROR("%s", e.what());
219  }
220  previous_errno = errno;
221  continue;
222  }
223 
224  if (user_notified_of_timeout || 0 != previous_errno)
225  {
226  ROS_INFO("Receiving data");
227  previous_errno = 0;
228  user_notified_of_timeout = false;
229  }
230 
231  if (!streaming_data)
232  {
233  streaming_data = true;
234  ROS_INFO("streaming data");
235  }
236 
237  bool parser_is_working = true;
238  int previous_temp_buffer_length = temp_buffer_length;
239  while (temp_buffer_length > 0 && parser_is_working)
240  {
241  ParseDsp3000Data const parsed_data(parse_dsp3000(temp_buffer, temp_buffer_length));
242  parser_is_working = previous_temp_buffer_length != parsed_data.new_buffer_length;
243  temp_buffer_length = parsed_data.new_buffer_length;
244  previous_temp_buffer_length = temp_buffer_length;
245 
246  if (parsed_data.did_parser_succeed)
247  {
248  if (!parsed_data.is_sensor_data_valid)
249  {
250  ROS_ERROR("Sensor data is invalid");
251  }
252  else
253  {
254  // Declare the sensor message
255  std_msgs::Float32 dsp_out;
256  float const rotation_measurement_rad = (parsed_data.value * PI) / 180.0f;
257  dsp_out.data = (invert ? -rotation_measurement_rad : rotation_measurement_rad);
258 
259  // Publish the joint state message
260  dsp3000_pub.publish(dsp_out);
261  }
262  }
263  else if (!ignoring_buffer_overflow && temporary_buffer_ignore_limit >= 100)
264  {
265  temp_buffer[temp_buffer_length] = '\0';
266  ROS_WARN("Bad data. Received data \"%s\" of length %i", temp_buffer, temp_buffer_length);
267  }
268  else
269  {
270  ++temporary_buffer_ignore_limit;
271  }
272  }
273 
274  ros::spinOnce();
275  }
276 
277  return 0;
278 }
KvhDsp3000Mode
Copyright Autonomous Solutions Inc. 2016.
Definition: dsp3000_mode.h:6
#define ROS_FATAL(...)
void publish(const boost::shared_ptr< M > &message) const
f
string get_mode_topic_name(KvhDsp3000Mode const mode)
static constexpr int TIMEOUT
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
#define ROS_WARN(...)
int write(const char *data, int length=-1)
Write to the port.
tuple< string, string > get_mode_data(KvhDsp3000Mode mode)
ParseDsp3000Data parse_dsp3000(char *buffer, int buffer_size)
void open(const char *port_name, int baud_rate=115200)
Open the serial port.
Definition: serial_port.cpp:73
#define ROS_INFO(...)
Copyright Autonomous Solutions Inc. 2016.
Definition: dsp3000_parser.h:8
ROSCPP_DECL bool ok()
int main(int argc, char **argv)
static constexpr float PI
bool configure_dsp3000(SerialPort *device, KvhDsp3000Mode mode)
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
C++ serial port class for ROS.
Definition: serial_port.h:80


kvh_drivers
Author(s): Jeff Schmidt, Geoffrey Viola
autogenerated on Mon Jun 10 2019 13:45:24