gpgsv.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2017, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL SOUTHWEST RESEARCH INSTITUTE BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // *****************************************************************************
29 
31 #include <boost/make_shared.hpp>
32 
33 const std::string novatel_gps_driver::GpgsvParser::MESSAGE_NAME = "GPGSV";
34 
36 {
37  return 0;
38 }
39 
41 {
42  return MESSAGE_NAME;
43 }
44 
45 novatel_gps_msgs::GpgsvPtr novatel_gps_driver::GpgsvParser::ParseAscii(const novatel_gps_driver::NmeaSentence& sentence) noexcept(false)
46 {
47  const size_t MIN_LENGTH = 4;
48  // Check that the message is at least as long as a a GPGSV with no satellites
49  if (sentence.body.size() < MIN_LENGTH)
50  {
51  std::stringstream error;
52  error << "Expected GPGSV length >= " << MIN_LENGTH
53  << ", actual length = " << sentence.body.size();
54  throw ParseException(error.str());
55  }
56  novatel_gps_msgs::GpgsvPtr msg = boost::make_shared<novatel_gps_msgs::Gpgsv>();
57  msg->message_id = sentence.body[0];
58  if (!ParseUInt8(sentence.body[1], msg->n_msgs))
59  {
60  throw new ParseException("Error parsing n_msgs in GPGSV.");
61  }
62  if (msg->n_msgs > 9) // Check that number of messages <= 9
63  {
64  std::stringstream error;
65  error << "n_msgs in GPGSV was too large (" << msg->n_msgs << ").";
66  throw ParseException(error.str());
67  }
68 
69  if (!ParseUInt8(sentence.body[2], msg->msg_number))
70  {
71  throw ParseException("Error parsing msg_number in GPGSV.");
72  }
73  if (msg->msg_number > msg->n_msgs) // Check that this message is within the sequence range
74  {
75  std::stringstream error;
76  error << "msg_number in GPGSV was larger than n_msgs (" << msg->msg_number << " > " << msg->n_msgs << ").";
77  throw ParseException(error.str());
78  }
79  if (!ParseUInt8(sentence.body[3], msg->n_satellites))
80  {
81  throw ParseException("Error parsing n_satellites in GPGSV.");
82  }
83 
84 
85  // Figure out how many satellites should be described in this sentence
86  size_t n_sats_in_sentence = 4;
87  if (msg->msg_number == msg->n_msgs)
88  {
89  n_sats_in_sentence = msg->n_satellites % static_cast<uint8_t>(4);
90  }
91  // Check that the sentence is the right length for the number of satellites
92  size_t expected_length = MIN_LENGTH + 4 * n_sats_in_sentence;
93  if (n_sats_in_sentence == 0)
94  {
95  // Even if the number of sats is 0, the message will still have enough
96  // blank fields for 1 satellite.
97  expected_length += 4;
98  }
99  if (sentence.body.size() != expected_length && sentence.body.size() != expected_length -1)
100  {
101  std::stringstream ss;
102  for (size_t i = 0; i < sentence.body.size(); ++i)
103  {
104  ss << sentence.body[i];
105  if ((i+1) < sentence.body.size())
106  {
107  ss << ",";
108  }
109  }
110  std::stringstream error;
111  error << "Expected GPGSV length = " << expected_length << " for message with "
112  << n_sats_in_sentence << " satellites, actual length = "
113  << sentence.body.size() << "\n" << ss.str().c_str();
114  throw ParseException(error.str());
115  }
116  msg->satellites.resize(n_sats_in_sentence);
117  for (size_t sat = 0, index=MIN_LENGTH; sat < n_sats_in_sentence; ++sat, index += 4)
118  {
119  if (!ParseUInt8(sentence.body[index], msg->satellites[sat].prn))
120  {
121  std::stringstream error;
122  error << "Error parsing prn for satellite " << sat << " in GPGSV.";
123  throw ParseException(error.str());
124  }
125 
126  float elevation;
127  if (!ParseFloat(sentence.body[index + 1], elevation))
128  {
129  std::stringstream error;
130  error << "Error parsing elevation for satellite " << sat << " in GPGSV.";
131  throw ParseException(error.str());
132  }
133  msg->satellites[sat].elevation = static_cast<uint8_t>(elevation);
134 
135  float azimuth;
136  if (!ParseFloat(sentence.body[index + 2], azimuth))
137  {
138  std::stringstream error;
139  error << "Error parsing azimuth for satellite " << sat << " in GPGSV.";
140  throw ParseException(error.str());
141  }
142  msg->satellites[sat].azimuth = static_cast<uint16_t>(azimuth);
143 
144  if ((index + 3) >= sentence.body.size() || sentence.body[index + 3].empty())
145  {
146  msg->satellites[sat].snr = -1;
147  }
148  else
149  {
150  uint8_t snr;
151  if (!ParseUInt8(sentence.body[index + 3], snr))
152  {
153  std::stringstream error;
154  error << "Error parsing snr for satellite " << sat << " in GPGSV.";
155  throw ParseException(error.str());
156  }
157 
158  msg->satellites[sat].snr = static_cast<int8_t>(snr);
159  }
160  }
161  return msg;
162 }
msg
const std::string GetMessageName() const override
Definition: gpgsv.cpp:40
bool ParseUInt8(const std::string &string, uint8_t &value, int32_t base=10)
Parses a string containing an integer number into a uint16_t.
static const std::string MESSAGE_NAME
Definition: gpgsv.h:47
novatel_gps_msgs::GpgsvPtr ParseAscii(const NmeaSentence &sentence) noexcept(false) override
Converts sentence into a ROS message pointer and returns it.
Definition: gpgsv.cpp:45
float ParseFloat(const uint8_t *buffer)
Converts a buffer containing 4 bytes into a float.
uint32_t GetMessageId() const override
Definition: gpgsv.cpp:35


novatel_gps_driver
Author(s):
autogenerated on Thu Jul 16 2020 03:17:30