os32c.cpp
Go to the documentation of this file.
1 
27 #include <ros/ros.h>
28 #include <boost/shared_ptr.hpp>
29 #include <boost/make_shared.hpp>
30 #include <boost/asio.hpp>
31 
38 
39 using std::cout;
40 using std::endl;
41 using boost::shared_ptr;
42 using boost::make_shared;
43 using boost::asio::buffer;
44 using eip::Session;
47 using eip::CPFItem;
48 using eip::CPFPacket;
52 
53 namespace omron_os32c_driver {
54 
55 const double OS32C::ANGLE_MIN = DEG2RAD(-135.2);
56 const double OS32C::ANGLE_MAX = DEG2RAD(135.2);
57 const double OS32C::ANGLE_INC = DEG2RAD(0.4);
58 const double OS32C::DISTANCE_MIN = 0.002;
59 const double OS32C::DISTANCE_MAX = 50;
60 
62 {
65 }
66 
68 {
69  setSingleAttribute(0x73, 1, 4, format);
70  mrc_.range_report_format = format;
71 }
72 
74 {
77 }
78 
80 {
81  setSingleAttribute(0x73, 1, 5, format);
83 }
84 
85 void OS32C::calcBeamMask(double start_angle, double end_angle, EIP_BYTE mask[])
86 {
87  if (start_angle > (ANGLE_MAX + ANGLE_INC / 2))
88  {
89  throw std::invalid_argument("Start angle is greater than max");
90  }
91  if (end_angle < (ANGLE_MIN - ANGLE_INC / 2))
92  {
93  throw std::invalid_argument("End angle is greater than max");
94  }
95  if (start_angle - end_angle <= ANGLE_INC)
96  {
97  throw std::invalid_argument("Starting angle is less than ending angle");
98  }
99 
100  int start_beam = calcBeamNumber(start_angle);
101  int end_beam = calcBeamNumber(end_angle);
102  start_angle_ = calcBeamCentre(start_beam);
103  end_angle_ = calcBeamCentre(end_beam);
104 
105  // figure out where we're starting and ending in the array
106  int start_byte = start_beam / 8;
107  int start_bit = start_beam - start_byte * 8;
108  int end_byte = end_beam / 8;
109  int end_bit = end_beam - end_byte * 8;
110 
111  // clear out all of the whole bytes that need to be set in one shot
112  if (start_byte > 0)
113  {
114  memset(mask, 0, start_byte);
115  }
116 
117  // if we're starting in the middle of the byte, then we need to do some bit math
118  if (start_bit)
119  {
120  // clear out the bits at the start of the byte, while making the higher bits 1
121  mask[start_byte] = ~((1 << start_bit) - 1);
122  }
123  else
124  {
125  --start_byte;
126  }
127 
128  // mark all of the whole bytes
129  memset(mask + start_byte + 1, 0xFF, end_byte - start_byte - 1);
130 
131  // clear out the bits above the end beam
132  mask[end_byte] = (1 << (end_bit + 1)) - 1;
133 
134  // zero out everything after the end
135  memset(mask + end_byte + 1, 0, 87 - end_byte);
136 }
137 
138 void OS32C::selectBeams(double start_angle, double end_angle)
139 {
140  calcBeamMask(start_angle, end_angle, mrc_.beam_selection_mask);
141  shared_ptr<SerializableBuffer> sb = make_shared<SerializableBuffer>(buffer(mrc_.beam_selection_mask));
142  setSingleAttributeSerializable(0x73, 1, 12, sb);
143 }
144 
146 {
148  getSingleAttributeSerializable(0x75, 1, 3, rr);
149  return rr;
150 }
151 
152 void OS32C::fillLaserScanStaticConfig(sensor_msgs::LaserScan* ls)
153 {
154  ls->angle_max = start_angle_;
155  ls->angle_min = end_angle_;
156  ls->angle_increment = ANGLE_INC;
157  ls->range_min = DISTANCE_MIN;
158  ls->range_max = DISTANCE_MAX;
159 }
160 
161 void OS32C::convertToLaserScan(const RangeAndReflectanceMeasurement& rr, sensor_msgs::LaserScan* ls)
162 {
163  if (rr.range_data.size() != rr.header.num_beams || rr.reflectance_data.size() != rr.header.num_beams)
164  {
165  throw std::invalid_argument("Number of beams does not match vector size");
166  }
167 
168  // Beam period is in ns
169  ls->time_increment = rr.header.scan_beam_period / 1000000000.0;
170  // Scan period is in microseconds.
171  ls->scan_time = rr.header.scan_rate / 1000000.0;
172 
173  // TODO: this currently makes assumptions of the report format. Should likely
174  // accomodate all of them, or at least anything reasonable.
175  ls->ranges.resize(rr.header.num_beams);
176  ls->intensities.resize(rr.header.num_beams);
177  for (int i = 0; i < rr.header.num_beams; ++i)
178  {
179  if (rr.range_data[i] == 0x0001)
180  {
181  // noisy beam detected
182  ls->ranges[i] = 0;
183  }
184  else if (rr.range_data[i] == 0xFFFF)
185  {
186  // no return
187  ls->ranges[i] = DISTANCE_MAX;
188  }
189  else
190  {
191  ls->ranges[i] = rr.range_data[i] / 1000.0;
192  }
193  ls->intensities[i] = rr.reflectance_data[i];
194  }
195 }
196 
197 void OS32C::convertToLaserScan(const MeasurementReport& mr, sensor_msgs::LaserScan* ls)
198 {
199  if (mr.measurement_data.size() != mr.header.num_beams)
200  {
201  throw std::invalid_argument("Number of beams does not match vector size");
202  }
203 
204  // Beam period is in ns.
205  ls->time_increment = mr.header.scan_beam_period / 1000000000.0;
206  // Scan period is in microseconds.
207  ls->scan_time = mr.header.scan_rate / 1000000.0;
208 
209  // TODO: this currently makes assumptions of the report format. Should likely
210  // accomodate all of them, or at least anything reasonable.
211  ls->ranges.resize(mr.header.num_beams);
212  for (int i = 0; i < mr.header.num_beams; ++i)
213  {
214  if (mr.measurement_data[i] == 0x0001)
215  {
216  // noisy beam detected
217  ls->ranges[i] = 0;
218  }
219  else if (mr.measurement_data[i] == 0xFFFF)
220  {
221  // no return
222  ls->ranges[i] = DISTANCE_MAX;
223  }
224  else
225  {
226  ls->ranges[i] = mr.measurement_data[i] / 1000.0;
227  }
228  }
229 }
230 
232 {
233  // TODO: check that connection is valid
234  CPFPacket pkt;
236  make_shared<SequencedAddressItem>(getConnection(connection_num_).o_to_t_connection_id, mrc_sequence_num_++);
237  shared_ptr<MeasurementReportConfig> data = make_shared<MeasurementReportConfig>();
238  *data = mrc_;
239  pkt.getItems().push_back(CPFItem(0x8002, address));
240  pkt.getItems().push_back(CPFItem(0x00B1, data));
241  sendIOPacket(pkt);
242 }
243 
245 {
246  CPFPacket pkt = receiveIOPacket();
247  if (pkt.getItemCount() != 2)
248  {
249  throw std::logic_error("IO Packet received with wrong number of items");
250  }
251  if (pkt.getItems()[1].getItemType() != 0x00B1)
252  {
253  throw std::logic_error("IO Packet received with wrong data type");
254  }
255 
257  pkt.getItems()[1].getDataAs(data);
258  return data;
259 }
260 
262 {
263  EIP_CONNECTION_INFO_T o_to_t, t_to_o;
264  o_to_t.assembly_id = 0x71;
265  o_to_t.buffer_size = 0x006E;
266  o_to_t.rpi = 0x00177FA0;
267  t_to_o.assembly_id = 0x66;
268  t_to_o.buffer_size = 0x0584;
269  t_to_o.rpi = 0x00013070;
270 
271  connection_num_ = createConnection(o_to_t, t_to_o);
272  ROS_INFO("Opened connection with id %d", connection_num_);
273 }
274 
276 {
277  if (connection_num_ >= 0)
278  {
279  ROS_INFO("Closing connection with id %d", connection_num_);
281  }
282 }
283 
284 } // namespace omron_os32c_driver
MeasurementReportConfig mrc_
Definition: os32c.h:217
static const double ANGLE_INC
Definition: os32c.h:93
void selectBeams(double start_angle, double end_angle)
Definition: os32c.cpp:138
CPFPacket receiveIOPacket()
EIP_UINT getReflectivityFormat()
Definition: os32c.cpp:73
static const double ANGLE_MAX
Definition: os32c.h:92
RangeAndReflectanceMeasurement getSingleRRScan()
Definition: os32c.cpp:145
data
void closeConnection(size_t n)
static int calcBeamNumber(double angle)
Definition: os32c.h:157
void setReflectivityFormat(EIP_UINT format)
Definition: os32c.cpp:79
void sendIOPacket(CPFPacket &pkt)
void setRangeFormat(EIP_UINT format)
Definition: os32c.cpp:67
EIP_UINT getRangeFormat()
Definition: os32c.cpp:61
EIP_UDINT o_to_t_connection_id
uint8_t EIP_BYTE
#define ROS_INFO(...)
static double calcBeamCentre(int beam_num)
Definition: os32c.h:168
void setSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT instance_id, EIP_USINT attribute_id, shared_ptr< Serializable > data)
static const double DISTANCE_MAX
Definition: os32c.h:95
int createConnection(const EIP_CONNECTION_INFO_T &o_to_t, const EIP_CONNECTION_INFO_T &t_to_o)
uint16_t EIP_UINT
void setSingleAttribute(EIP_USINT class_id, EIP_USINT instance_id, EIP_USINT attribute_id, T v)
void calcBeamMask(double start_angle, double end_angle, EIP_BYTE mask[])
Definition: os32c.cpp:85
MeasurementReport receiveMeasurementReportUDP()
Definition: os32c.cpp:244
const Connection & getConnection(size_t n)
EIP_UDINT mrc_sequence_num_
Definition: os32c.h:218
static const double ANGLE_MIN
Definition: os32c.h:91
static void convertToLaserScan(const RangeAndReflectanceMeasurement &rr, sensor_msgs::LaserScan *ls)
Definition: os32c.cpp:161
void sendMeasurmentReportConfigUDP()
Definition: os32c.cpp:231
void fillLaserScanStaticConfig(sensor_msgs::LaserScan *ls)
Definition: os32c.cpp:152
T getSingleAttribute(EIP_USINT class_id, EIP_USINT instance_id, EIP_USINT attribute_id, T v)
vector< CPFItem > & getItems()
static const double DISTANCE_MIN
Definition: os32c.h:94
void getSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT instance_id, EIP_USINT attribute_id, Serializable &result)
#define DEG2RAD(a)
Definition: os32c.h:47
EIP_UINT getItemCount() const


omron_os32c_driver
Author(s): Kareem Shehata
autogenerated on Fri Nov 27 2020 03:06:12