communication_core.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // © Copyright 2020, Septentrio NV/SA.
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 // 1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // 2. 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 // 3. Neither the name of the copyright holder nor the names of its
14 // contributors may be used to endorse or promote products derived
15 // 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 // *****************************************************************************
30 
31 #include <chrono>
32 #include <filesystem>
33 #include <fstream>
34 #include <linux/serial.h>
35 
36 // Boost includes
37 #include <boost/regex.hpp>
39 
40 static const int16_t ANGLE_MAX = 180;
41 static const int16_t ANGLE_MIN = -180;
42 static const int8_t THETA_Y_MAX = 90;
43 static const int8_t THETA_Y_MIN = -90;
44 static const int8_t LEVER_ARM_MAX = 100;
45 static const int8_t LEVER_ARM_MIN = -100;
46 static const int16_t HEADING_MAX = 360;
47 static const int16_t HEADING_MIN = -360;
48 static const int8_t PITCH_MAX = 90;
49 static const int8_t PITCH_MIN = -90;
50 static const int8_t ATTSTD_DEV_MIN = 0;
51 static const int8_t ATTSTD_DEV_MAX = 5;
52 static const int8_t POSSTD_DEV_MIN = 0;
53 static const int8_t POSSTD_DEV_MAX = 100;
54 
61 namespace io {
62 
64  node_(node), settings_(node->settings()), telegramHandler_(node),
65  running_(true)
66  {
67  running_ = true;
68 
70  std::thread(std::bind(&CommunicationCore::processTelegrams, this));
71  }
72 
74  {
76 
77  resetSettings();
78 
79  running_ = false;
80  auto telegram = std::make_shared<Telegram>();
81  telegramQueue_.push(telegram);
82  processingThread_.join();
83  }
84 
85  void CommunicationCore::close() { manager_->close(); }
86 
88  {
89  if (!manager_->connected())
90  return;
93  {
95  send("sdio, " + mainConnectionPort_ + ", auto, none\x0D");
96  // Turning off all current SBF/NMEA output
97  send("sso, all, none, none, off \x0D");
98  send("sno, all, none, none, off \x0D");
99  if ((settings_->udp_port != 0) && (!settings_->udp_ip_server.empty()))
100  {
101  send("siss, " + settings_->udp_ip_server + ", 0\x0D");
102  }
103  for (auto ntrip : settings_->rtk.ntrip)
104  {
105  if (!ntrip.id.empty() && !ntrip.keep_open)
106  {
107  send("snts, " + ntrip.id + ", off \x0D");
108  }
109  }
110  for (auto ip_server : settings_->rtk.ip_server)
111  {
112  if (!ip_server.id.empty() && !ip_server.keep_open)
113  {
114  send("sdio, " + ip_server.id + ", auto, none\x0D");
115  send("siss, " + ip_server.id + ", 0\x0D");
116  }
117  }
118  for (auto serial : settings_->rtk.serial)
119  {
120  if (!serial.port.empty() && !serial.keep_open)
121  {
122  send("sdio, " + serial.port + ", auto, none\x0D");
123  if (serial.port.rfind("COM", 0) == 0)
124  send("scs, " + serial.port +
125  ", baud115200, bits8, No, bit1, none\x0D");
126  }
127  }
128  if (!settings_->ins_vsm.ip_server.empty())
129  {
131  {
132  send("sdio, " + settings_->ins_vsm.ip_server +
133  ", auto, none\x0D");
134  send("siss, " + settings_->ins_vsm.ip_server + ", 0\x0D");
135  }
136  }
137  if (!settings_->ins_vsm.serial_port.empty())
138  {
140  {
141  if (settings_->ins_vsm.serial_port.rfind("COM", 0) == 0)
142  send("scs, " + settings_->ins_vsm.serial_port +
143  ", baud115200, bits8, No, bit1, none\x0D");
144  send("sdio, " + settings_->ins_vsm.serial_port +
145  ", auto, none\x0D");
146  }
147  }
148  if (!settings_->osnma.keep_open && (settings_->osnma.mode == "loose" ||
149  settings_->osnma.mode == "strict"))
150  {
151  std::stringstream ss;
152  ss << "sou, off \x0D";
153  send(ss.str());
154 
155  if (!settings_->osnma.ntp_server.empty())
156  {
157  std::stringstream ss;
158  ss << "snc, off \x0D";
159  send(ss.str());
160  }
161  }
162 
163  if (!settings_->login_user.empty() && !settings_->login_password.empty())
164  send("logout \x0D");
165  }
166  }
167 
169  {
170  node_->log(log_level::DEBUG, "Called connect() method");
171  node_->log(
173  "Started timer for calling connect() method until connection succeeds");
174 
175  boost::asio::io_context io;
176  if (initializeIo())
177  {
178  initializedIo_ = manager_->connect();
179  if (!initializedIo_)
180  return;
181  }
182  // If node is shut down before a connection could be established
183  if (!node_->ok())
184  return;
185 
186  // Sends commands to the Rx regarding which SBF/NMEA messages it should
187  // output
188  // and sets all its necessary corrections-related parameters
190  {
191 
192  node_->log(log_level::DEBUG, "Configure Rx.");
193  configureRx();
194  }
195 
196  node_->log(log_level::INFO, "Setup complete.");
197 
199  "Successully connected. Leaving connect() method");
200  }
201 
202  [[nodiscard]] bool CommunicationCore::initializeIo()
203  {
204  bool client = false;
205  node_->log(log_level::DEBUG, "Called initializeIo() method");
206  if ((settings_->tcp_port != 0) && (!settings_->tcp_ip_server.empty()))
207  {
208  tcpClient_ =
209  std::make_unique<AsyncManager<TcpIo>>(node_, &telegramQueue_);
210  tcpClient_->setPort(std::to_string(settings_->tcp_port));
211  if (!settings_->configure_rx)
212  tcpClient_->connect();
213  client = true;
214  }
215  if ((settings_->udp_port != 0) && (!settings_->udp_ip_server.empty()))
216  {
217  udpClient_ = std::make_unique<UdpClient>(node_, settings_->udp_port,
218  &telegramQueue_);
219  client = true;
220  }
221 
222  switch (settings_->device_type)
223  {
224  case device_type::TCP:
225  {
226  manager_ = std::make_unique<AsyncManager<TcpIo>>(node_, &telegramQueue_);
227  break;
228  }
229  case device_type::SERIAL:
230  {
231  manager_ =
232  std::make_unique<AsyncManager<SerialIo>>(node_, &telegramQueue_);
233  break;
234  }
236  {
237  manager_ =
238  std::make_unique<AsyncManager<SbfFileIo>>(node_, &telegramQueue_);
239  break;
240  }
242  {
243  manager_ =
244  std::make_unique<AsyncManager<PcapFileIo>>(node_, &telegramQueue_);
245  break;
246  }
247  default:
248  {
249  if (!client || settings_->configure_rx ||
250  (settings_->ins_vsm.ros_source == "odometry") ||
251  (settings_->ins_vsm.ros_source == "twist"))
252  {
253  node_->log(log_level::DEBUG, "Unsupported device.");
254  return false;
255  }
256  break;
257  }
258  }
259  return true;
260  }
261 
270  {
271  node_->log(log_level::DEBUG, "Called configureRx() method");
272 
273  if (!initializedIo_)
274  {
276  "Called configureRx() method but IO is not initialized.");
277  return;
278  }
279 
280  uint8_t stream = 1;
281  // Determining communication mode: TCP vs USB/Serial
282  boost::smatch match;
283  boost::regex_match(settings_->device, match,
284  boost::regex("(tcp)://(.+):(\\d+)"));
285  std::string proto(match[1]);
288  "The connection descriptor is " + mainConnectionPort_);
290 
291  if (settings_->configure_rx)
292  {
293  node_->log(log_level::INFO, "Setting up Rx.");
294 
295  std::string pvt_interval =
298 
299  std::string rest_interval =
302 
303  // Credentials for login
304  if (!settings_->login_user.empty() && !settings_->login_password.empty())
305  {
307  send("login, " + settings_->login_user + ", \"" +
308  settings_->login_password + "\" \x0D");
309  else
310  send("login, " + settings_->login_user + ", " +
311  settings_->login_password + " \x0D");
312  }
313 
314  // Turning off all current SBF/NMEA output
315  send("sso, all, none, none, off \x0D");
316  send("sno, all, none, none, off \x0D");
317 
318  if (!settings_->custom_commands_file.empty())
319  {
320  if ((std::filesystem::exists(settings_->custom_commands_file)))
321  {
322  std::ifstream filestream(settings_->custom_commands_file);
323  node_->log(log_level::INFO, "Custom command file " +
325  " loaded.");
326 
327  size_t ctr = 0;
328  std::string line;
329  while (std::getline(filestream, line))
330  {
331  ++ctr;
332  send(line + "\x0D");
333  }
334  node_->log(
336  std::to_string(ctr) +
337  " custom commands have been parsed and sent to the Rx.");
338  } else
339  {
341  "Custom command file " +
343  " could not be found.");
344  }
345  }
346 
347  if (tcpClient_)
348  {
350  std::string tcp_mode;
352  tcp_mode = "TCP2Way";
353  else
354  tcp_mode = "TCP";
355  send("siss, " + streamPort_ + ", " +
356  std::to_string(settings_->tcp_port) + ", " + tcp_mode + ", " +
357  "\x0D");
358  tcpClient_->connect();
359  } else if (udpClient_)
360  {
362  std::string destination;
363  if (!settings_->udp_unicast_ip.empty())
364  destination = settings_->udp_unicast_ip;
365  else
366  destination = "255.255.255.255";
367  send("siss, " + streamPort_ + ", " +
368  std::to_string(settings_->udp_port) + ", UDP, " + destination +
369  "\x0D");
370  }
371 
372  // Get Rx capabilities
373  send("grc \x0D");
375 
376  // Activate NTP server
377  if (settings_->ntp_server)
378  send("sntp, on \x0D");
379 
380  // Activate PTP server clock
382  send("sptp, on \x0D");
383 
384  // Setting the datum to be used by the Rx (not the NMEA output though,
385  // which only provides MSL and undulation (by default with respect to
386  // WGS84), but not ellipsoidal height)
387  {
388  std::stringstream ss;
389  ss << "sgd, " << settings_->datum << "\x0D";
390  send(ss.str());
391  }
392 
393  if ((settings_->septentrio_receiver_type == "ins") || node_->isIns())
394  {
395  {
396  std::stringstream ss;
397  ss << "sat, Main, \"" << settings_->ant_type << "\"" << "\x0D";
398  send(ss.str());
399  }
400 
401  // Configure Aux1 antenna
403  {
404  std::stringstream ss;
405  ss << "sat, Aux1, \"" << settings_->ant_type << "\"" << "\x0D";
406  send(ss.str());
407  }
408  } else if (settings_->septentrio_receiver_type == "gnss")
409  {
410  // Setting the marker-to-ARP offsets. This comes after the "sso, ...,
411  // ReceiverSetup, ..." command, since the latter is only generated
412  // when a user-command is entered to change one or more values in the
413  // block.
414  {
415  std::stringstream ss;
416  ss << "sao, Main, "
418  << ", "
420  << ", "
422  << ", \"" << settings_->ant_type << "\", "
423  << settings_->ant_serial_nr << "\x0D";
424  send(ss.str());
425  }
426 
427  // Configure Aux1 antenna
429  {
430  std::stringstream ss;
431  ss << "sao, Aux1, " << string_utilities::trimDecimalPlaces(0.0)
432  << ", " << string_utilities::trimDecimalPlaces(0.0) << ", "
433  << string_utilities::trimDecimalPlaces(0.0) << ", \""
434  << settings_->ant_aux1_type << "\", "
435  << settings_->ant_aux1_serial_nr << "\x0D";
436  send(ss.str());
437  }
438  }
439 
440  // Configuring the corrections connection
441  for (auto ntrip : settings_->rtk.ntrip)
442  {
443  if (!ntrip.id.empty())
444  {
445  // First disable any existing NTRIP connection on NTR1
446  send("snts, " + ntrip.id + ", off \x0D");
447  {
448  std::stringstream ss;
449  ss << "snts, " << ntrip.id << ", Client, " << ntrip.caster
450  << ", " << std::to_string(ntrip.caster_port) << ", "
451  << ntrip.username << ", " << ntrip.password << ", "
452  << ntrip.mountpoint << ", " << ntrip.version << ", "
453  << ntrip.send_gga << " \x0D";
454  send(ss.str());
455  }
456  if (ntrip.tls)
457  {
458  std::stringstream ss;
459  ss << "sntt, " << ntrip.id << ", on, \"" << ntrip.fingerprint
460  << "\" \x0D";
461  send(ss.str());
462  } else
463  {
464  std::stringstream ss;
465  ss << "sntt, " << ntrip.id << ", off \x0D";
466  send(ss.str());
467  }
468  }
469  }
470 
471  for (auto ip_server : settings_->rtk.ip_server)
472  {
473  if (!ip_server.id.empty())
474  {
475  {
476  std::stringstream ss;
477  // In case this IP server was used before, old
478  // configuration is lost of course.
479  ss << "siss, " << ip_server.id << ", "
480  << std::to_string(ip_server.port) << ", TCP2Way \x0D";
481  send(ss.str());
482  }
483  {
484  std::stringstream ss;
485  ss << "sdio, " << ip_server.id << ", "
486  << ip_server.rtk_standard << ", +SBF+NMEA \x0D";
487  send(ss.str());
488  }
489  if (ip_server.send_gga != "off")
490  {
491  std::string rate = ip_server.send_gga;
492  if (ip_server.send_gga == "auto")
493  rate = "sec1";
494  std::stringstream ss;
495  ss << "sno, Stream" << std::to_string(stream) << ", "
496  << ip_server.id << ", GGA, " << rate << " \x0D";
497  ++stream;
498  send(ss.str());
499  }
500  }
501  }
502 
503  for (auto serial : settings_->rtk.serial)
504  {
505  if (!serial.port.empty())
506  {
507  if (serial.port.rfind("COM", 0) == 0)
508  send("scs, " + serial.port + ", baud" +
509  std::to_string(serial.baud_rate) +
510  ", bits8, No, bit1, none\x0D");
511 
512  std::stringstream ss;
513  ss << "sdio, " << serial.port << ", " << serial.rtk_standard
514  << ", +SBF+NMEA \x0D";
515  send(ss.str());
516  if (serial.send_gga != "off")
517  {
518  std::string rate = serial.send_gga;
519  if (serial.send_gga == "auto")
520  rate = "sec1";
521  std::stringstream ss;
522  ss << "sno, Stream" << std::to_string(stream) << ", "
523  << serial.port << ", GGA, " << rate << " \x0D";
524  ++stream;
525  send(ss.str());
526  }
527  }
528  }
529 
530  // Setting multi antenna
532  {
533  if (node_->hasHeading())
534  send("sga, MultiAntenna \x0D");
535  else
536  node_->log(
538  "Multi antenna requested but Rx does not support it.");
539  } else
540  {
541  send("sga, none \x0D");
542  }
543 
544  // Setting the Attitude Determination
545  {
550  {
551  std::stringstream ss;
552  ss << "sto, "
555  << ", "
558  << " \x0D";
559  send(ss.str());
560  } else
561  {
562  node_->log(
564  "Please specify a valid parameter for heading and pitch");
565  }
566  }
567 
568  // Setting the INS-related commands
569  if (settings_->septentrio_receiver_type == "ins")
570  {
571  // IMU orientation
572  {
573  std::stringstream ss;
574  if (settings_->theta_x >= ANGLE_MIN &&
580  {
581  ss << " sio, " << "manual" << ", "
583  << ", "
585  << ", "
587  << " \x0D";
588  send(ss.str());
589  } else
590  {
591  node_->log(
593  "Please specify a correct value for IMU orientation angles");
594  }
595  }
596 
597  // Setting the INS antenna lever arm offset
598  {
605  {
606  std::stringstream ss;
607  ss << "sial, "
610  << ", "
613  << ", "
616  << " \x0D";
617  send(ss.str());
618  } else
619  {
620  node_->log(
622  "Please specify a correct value for x, y and z in the config file under ant_lever_arm");
623  }
624  }
625 
626  // Setting the user defined point offset
627  {
628  if (settings_->poi_x >= LEVER_ARM_MIN &&
634  {
635  std::stringstream ss;
636  ss << "sipl, POI1, "
638  << ", "
640  << ", "
642  << " \x0D";
643  send(ss.str());
644  } else
645  {
646  node_->log(
648  "Please specify a correct value for poi_x, poi_y and poi_z in the config file under poi_lever_arm");
649  }
650  }
651 
652  // Setting the Velocity sensor lever arm offset
653  {
654  if (settings_->vsm_x >= LEVER_ARM_MIN &&
660  {
661  std::stringstream ss;
662  ss << "sivl, VSM1, "
664  << ", "
666  << ", "
668  << " \x0D";
669  send(ss.str());
670  } else
671  {
672  node_->log(
674  "Please specify a correct value for vsm_x, vsm_y and vsm_z in the config file under vsm_lever_arm");
675  }
676  }
677 
678  // Setting the INS Solution Reference Point: MainAnt or POI1
679  // First disable any existing INS sub-block connection
680  {
681  std::stringstream ss;
682  ss << "sinc, off, all, MainAnt \x0D";
683  send(ss.str());
684  }
685 
686  // INS solution reference point
687  {
688  std::stringstream ss;
689  if (settings_->ins_use_poi)
690  {
691  ss << "sinc, on, all, " << "POI1" << " \x0D";
692  send(ss.str());
693  } else
694  {
695  ss << "sinc, on, all, " << "MainAnt" << " \x0D";
696  send(ss.str());
697  }
698  }
699 
700  // Setting the INS heading
701  {
702  std::stringstream ss;
703  if (settings_->ins_initial_heading == "auto")
704  {
705  ss << "siih, " << settings_->ins_initial_heading << " \x0D";
706  send(ss.str());
707  } else if (settings_->ins_initial_heading == "stored")
708  {
709  ss << "siih, " << settings_->ins_initial_heading << " \x0D";
710  send(ss.str());
711  } else
712  {
713  node_->log(
715  "Invalid mode specified for ins_initial_heading.");
716  }
717  }
718 
719  // Setting the INS navigation filter
720  {
725  {
726  std::stringstream ss;
727  ss << "sism, "
730  << ", "
733  << " \x0D";
734  send(ss.str());
735  } else
736  {
738  "Please specify a valid AttStsDev and PosStdDev");
739  }
740  }
741  }
742 
743  // OSNMA
744  if (settings_->osnma.mode == "loose" ||
745  settings_->osnma.mode == "strict")
746  {
747  std::stringstream ss;
748  ss << "sou, " << settings_->osnma.mode << " \x0D";
749  send(ss.str());
750 
751  if (!settings_->osnma.ntp_server.empty())
752  {
753  std::stringstream ss;
754  ss << "snc, on, " << settings_->osnma.ntp_server << " \x0D";
755  send(ss.str());
756  } else
757  {
758  if (settings_->osnma.mode == "strict")
759  node_->log(
761  "OSNMA mode set to strict but no NTP server provided. In Strict mode an NTP server is mandatory!");
762  }
763  }
764 
765  // Setting up SBF blocks with rx_period_rest
766  {
767  std::stringstream blocks;
768  if (settings_->septentrio_receiver_type == "ins")
769  {
771  {
772  blocks << " +IMUSetup";
773  }
775  {
776  blocks << " +VelSensorSetup";
777  }
778  }
780  {
781  blocks << " +QualityInd";
782  }
784  {
785  blocks << " +RFStatus";
786  }
788  (settings_->osnma.mode == "loose") ||
789  (settings_->osnma.mode == "strict"))
790  {
791  blocks << " +GALAuthStatus";
792  }
793 
794  blocks << " +ReceiverSetup +ReceiverStatus";
795 
796  std::stringstream ss;
797  ss << "sso, Stream" << std::to_string(stream) << ", " << streamPort_
798  << "," << blocks.str() << ", " << rest_interval << "\x0D";
799  send(ss.str());
800  ++stream;
801  }
802 
803  // send command to trigger emission of receiver setup
804  send("sop, \"\", \"\" \x0D");
805 
806  // Setting up NMEA streams
807  {
808  if (settings_->septentrio_receiver_type == "ins")
809  send("snti, auto\x0D");
810  else
811  send("snti, GP\x0D");
812 
813  std::stringstream blocks;
815  {
816  blocks << " +GGA";
817  }
819  {
820  blocks << " +RMC";
821  }
823  {
824  blocks << " +GSA";
825  }
827  {
828  blocks << " +GSV";
829  }
830 
831  std::stringstream ss;
832  ss << "sno, Stream" << std::to_string(stream) << ", " << streamPort_
833  << "," << blocks.str() << ", " << pvt_interval << "\x0D";
834  send(ss.str());
835  ++stream;
836  }
837 
838  // Setting up SBF blocks with rx_period_pvt
839  {
840  std::stringstream blocks;
842  {
843  blocks << " +ReceiverTime";
844  }
846  {
847  blocks << " +PVTCartesian";
848  }
851  (settings_->septentrio_receiver_type == "gnss")) ||
853  (settings_->septentrio_receiver_type == "gnss")) ||
855  (settings_->septentrio_receiver_type == "gnss")) ||
857  (settings_->septentrio_receiver_type == "gnss")) ||
859  {
860  blocks << " +PVTGeodetic";
861  }
863  {
864  blocks << " +BaseVectorCart";
865  }
867  {
868  blocks << " +BaseVectorGeod";
869  }
871  {
872  blocks << " +PosCovCartesian";
873  }
876  (settings_->septentrio_receiver_type == "gnss")) ||
878  (settings_->septentrio_receiver_type == "gnss")) ||
880  (settings_->septentrio_receiver_type == "gnss")))
881  {
882  blocks << " +PosCovGeodetic";
883  }
885  {
886  blocks << " +VelCovCartesian";
887  }
890  (settings_->septentrio_receiver_type == "gnss")))
891  {
892  blocks << " +VelCovGeodetic";
893  }
896  (settings_->septentrio_receiver_type == "gnss")) ||
898  (settings_->septentrio_receiver_type == "gnss")))
899  {
900  blocks << " +AttEuler";
901  }
904  (settings_->septentrio_receiver_type == "gnss")) ||
906  (settings_->septentrio_receiver_type == "gnss")))
907  {
908  blocks << " +AttCovEuler";
909  }
911  {
912  blocks << " +MeasEpoch";
913  }
915  {
916  blocks << " +ChannelStatus +DOP";
917  }
918  // Setting SBF output of Rx depending on the receiver type
919  // If INS then...
920  if (settings_->septentrio_receiver_type == "ins")
921  {
925  {
926  blocks << " +INSNavCart";
927  }
935  {
936  blocks << " +INSNavGeod";
937  }
939  {
940  blocks << " +ExtEventINSNavGeod";
941  }
943  {
944  blocks << " +ExtEventINSNavCart";
945  }
947  {
948  blocks << " +ExtSensorMeas";
949  }
950  }
951  std::stringstream ss;
952  ss << "sso, Stream" << std::to_string(stream) << ", " << streamPort_
953  << "," << blocks.str() << ", " << pvt_interval << "\x0D";
954  send(ss.str());
955  ++stream;
956  }
957 
958  if (settings_->septentrio_receiver_type == "ins")
959  {
960  if (!settings_->ins_vsm.ip_server.empty())
961  {
962  send("siss, " + settings_->ins_vsm.ip_server + ", " +
963  std::to_string(settings_->ins_vsm.ip_server_port) +
964  ", TCP2Way \x0D");
965  send("sdio, " + settings_->ins_vsm.ip_server +
966  ", NMEA, none\x0D");
967  }
968  if (!settings_->ins_vsm.serial_port.empty())
969  {
970  if (settings_->ins_vsm.serial_port.rfind("COM", 0) == 0)
971  send("scs, " + settings_->ins_vsm.serial_port + ", baud" +
972  std::to_string(settings_->ins_vsm.serial_baud_rate) +
973  ", bits8, No, bit1, none\x0D");
974  send("sdio, " + settings_->ins_vsm.serial_port + ", NMEA\x0D");
975  }
976 
977  if ((settings_->ins_vsm.ros_source == "odometry") ||
978  (settings_->ins_vsm.ros_source == "twist"))
979  {
981  {
982  send("sdio, " + settings_->tcp_ip_server +
983  ", NMEA, +NMEA +SBF\x0D");
984  } else if (!settings_->ins_vsm.ip_server.empty())
985  {
986  send("siss, " + settings_->ins_vsm.ip_server + ", " +
987  std::to_string(settings_->ins_vsm.ip_server_port) +
988  ", TCP2Way \x0D");
989 
990  send("sdio, " + settings_->ins_vsm.ip_server +
991  ", NMEA, none\x0D");
992  }
993  }
994  }
995  // Save config to boot
996  send("eccf, Current, Boot\x0D");
997  }
998 
999  if (settings_->septentrio_receiver_type == "ins")
1000  {
1001  if ((settings_->ins_vsm.ros_source == "odometry") ||
1002  (settings_->ins_vsm.ros_source == "twist"))
1003  {
1005  !settings_->ins_vsm.ip_server.empty())
1006  {
1007  tcpVsm_ = std::make_unique<AsyncManager<TcpIo>>(node_,
1008  &telegramQueue_);
1009  tcpVsm_->setPort(
1010  std::to_string(settings_->ins_vsm.ip_server_port));
1011  tcpVsm_->connect();
1012  }
1013  }
1014 
1015  nmeaActivated_ = true;
1016  }
1017 
1018  node_->log(log_level::DEBUG, "Leaving configureRx() method");
1019  }
1020 
1021  void CommunicationCore::sendVelocity(const std::string& velNmea)
1022  {
1023  if (nmeaActivated_)
1024  {
1026  {
1027  if (tcpClient_)
1028  tcpClient_.get()->send(velNmea);
1029  } else
1030  {
1031  if (tcpVsm_)
1032  tcpVsm_.get()->send(velNmea);
1033  }
1034  }
1035  }
1036 
1038  {
1039  // Escape sequence (escape from correction mode), ensuring that we
1040  // can send our real commands afterwards... has to be sent multiple times.
1041  std::string cmd("\x0DSSSSSSSSSS\x0D\x0D");
1043  manager_.get()->send(cmd);
1044  std::ignore = telegramHandler_.getMainCd();
1046  manager_.get()->send(cmd);
1047  std::ignore = telegramHandler_.getMainCd();
1049  manager_.get()->send(cmd);
1050  return telegramHandler_.getMainCd();
1051  }
1052 
1054  {
1055  while (running_)
1056  {
1057  std::shared_ptr<Telegram> telegram;
1058  telegramQueue_.pop(telegram);
1059 
1060  if (telegram->type != telegram_type::EMPTY)
1061  telegramHandler_.handleTelegram(telegram);
1062  }
1063  }
1064 
1065  void CommunicationCore::send(const std::string& cmd)
1066  {
1067  manager_.get()->send(cmd);
1069  }
1070 
1071 } // namespace io
Settings::osnma
Osnma osnma
OSNMA settings.
Definition: settings.hpp:253
log_level::WARN
@ WARN
Definition: typedefs.hpp:182
Settings::publish_pose
bool publish_pose
Whether or not to publish the PoseWithCovarianceStampedMsg message.
Definition: settings.hpp:320
PITCH_MIN
static const int8_t PITCH_MIN
Definition: communication_core.cpp:49
Settings::publish_attcoveuler
bool publish_attcoveuler
Whether or not to publish the AttCovEulerMsg message.
Definition: settings.hpp:298
io::CommunicationCore::resetSettings
void resetSettings()
Resets Rx settings.
Definition: communication_core.cpp:87
device_type::TCP
@ TCP
Definition: settings.hpp:141
Settings::ins_initial_heading
std::string ins_initial_heading
For heading computation when unit is powered-cycled.
Definition: settings.hpp:245
InsVsm::serial_port
std::string serial_port
VSM serial port.
Definition: settings.hpp:131
THETA_Y_MIN
static const int8_t THETA_Y_MIN
Definition: communication_core.cpp:43
io::CommunicationCore::tcpVsm_
std::unique_ptr< AsyncManager< TcpIo > > tcpVsm_
Definition: communication_core.hpp:174
Settings::latency_compensation
bool latency_compensation
Wether processing latency shall be compensated for in ROS timestamp.
Definition: settings.hpp:350
Osnma::keep_open
bool keep_open
Wether OSNMA shall be kept open on shutdown.
Definition: settings.hpp:44
Settings::publish_imusetup
bool publish_imusetup
Whether or not to publish the IMUSetupMsg message.
Definition: settings.hpp:304
Settings::publish_twist
bool publish_twist
Whether or not to publish the TwistWithCovarianceStampedMsg message.
Definition: settings.hpp:330
Settings::publish_localization
bool publish_localization
Whether or not to publish the LocalizationMsg message.
Definition: settings.hpp:326
Settings::pos_std_dev
float pos_std_dev
Position deviation mask.
Definition: settings.hpp:249
Rtk::serial
std::vector< RtkSerial > serial
Definition: settings.hpp:109
Settings::use_gnss_time
bool use_gnss_time
Definition: settings.hpp:344
io::TelegramHandler::resetWaitforMainCd
void resetWaitforMainCd()
Returns the connection descriptor.
Definition: telegram_handler.hpp:138
Settings::login_password
std::string login_password
Password for login.
Definition: settings.hpp:176
InsVsm::ip_server_keep_open
bool ip_server_keep_open
Wether VSM shall be kept open om shutdown.
Definition: settings.hpp:129
InsVsm::ros_source
std::string ros_source
VSM source for INS.
Definition: settings.hpp:115
communication_core.hpp
Highest-Level view on communication services.
Settings::publish_pvtcartesian
bool publish_pvtcartesian
Definition: settings.hpp:275
Settings::udp_ip_server
std::string udp_ip_server
UDP IP server id.
Definition: settings.hpp:166
io::TelegramHandler::getMainCd
std::string getMainCd()
Returns the connection descriptor.
Definition: telegram_handler.hpp:141
InsVsm::ip_server
std::string ip_server
VSM IP server id.
Definition: settings.hpp:125
Settings::publish_pvtgeodetic
bool publish_pvtgeodetic
Whether or not to publish the PVTGeodeticMsg message.
Definition: settings.hpp:277
Settings::heading_offset
double heading_offset
Attitude offset determination in longitudinal direction.
Definition: settings.hpp:237
ROSaicNodeBase::log
void log(log_level::LogLevel logLevel, const std::string &s) const
Log function to provide abstraction of ROS loggers.
Definition: typedefs.hpp:286
Settings::publish_gpgga
bool publish_gpgga
Whether or not to publish the GGA message.
Definition: settings.hpp:259
io::TelegramHandler::clearSemaphores
void clearSemaphores()
Definition: telegram_handler.hpp:126
Settings::publish_imu
bool publish_imu
Whether or not to publish the ImuMsg message.
Definition: settings.hpp:324
Osnma::ntp_server
std::string ntp_server
Server for NTP synchronization.
Definition: settings.hpp:42
Settings::multi_antenna
bool multi_antenna
INS multiantenna.
Definition: settings.hpp:241
Settings::vsm_x
double vsm_x
INS velocity sensor lever arm x-offset.
Definition: settings.hpp:231
Settings::udp_port
uint32_t udp_port
UDP port.
Definition: settings.hpp:162
InsVsm::serial_baud_rate
uint32_t serial_baud_rate
VSM serial baud rate.
Definition: settings.hpp:133
parsing_utilities::convertUserPeriodToRxCommand
std::string convertUserPeriodToRxCommand(uint32_t period_user)
Transforms the input polling period [milliseconds] into a std::string number that can be appended to ...
Definition: parsing_utilities.cpp:291
ANGLE_MIN
static const int16_t ANGLE_MIN
Definition: communication_core.cpp:41
Settings::ntp_server
bool ntp_server
Wether NTP server shall be activated.
Definition: settings.hpp:346
Settings::delta_n
float delta_n
Marker-to-ARP offset in the northward direction.
Definition: settings.hpp:197
Settings::polling_period_pvt
uint32_t polling_period_pvt
Polling period for PVT-related SBF blocks.
Definition: settings.hpp:191
Osnma::mode
std::string mode
OSNMA mode.
Definition: settings.hpp:40
io::CommunicationCore::tcpClient_
std::unique_ptr< AsyncManager< TcpIo > > tcpClient_
Definition: communication_core.hpp:171
io::CommunicationCore::nmeaActivated_
bool nmeaActivated_
Definition: communication_core.hpp:176
Settings::datum
std::string datum
Datum to be used.
Definition: settings.hpp:189
Settings::device_type
device_type::DeviceType device_type
Device type.
Definition: settings.hpp:156
Settings::theta_z
double theta_z
IMU orientation z-angle.
Definition: settings.hpp:217
Settings::publish_gpst
bool publish_gpst
Whether or not to publish the TimeReferenceMsg message with GPST.
Definition: settings.hpp:314
Settings::poi_y
double poi_y
INS POI offset in y-dimension.
Definition: settings.hpp:227
Settings::publish_galauthstatus
bool publish_galauthstatus
Whether or not to publish the GALAuthStatus message and diagnostics.
Definition: settings.hpp:272
ROSaicNodeBase::ok
bool ok()
Definition: typedefs.hpp:203
POSSTD_DEV_MAX
static const int8_t POSSTD_DEV_MAX
Definition: communication_core.cpp:53
Settings::publish_velcovcartesian
bool publish_velcovcartesian
Definition: settings.hpp:291
Settings::publish_aimplusstatus
bool publish_aimplusstatus
Definition: settings.hpp:270
Settings::poi_x
double poi_x
INS POI offset in x-dimension.
Definition: settings.hpp:225
io::CommunicationCore::configureRx
void configureRx()
Configures Rx: Which SBF/NMEA messages it should output and later correction settings.
Definition: communication_core.cpp:269
io::CommunicationCore::sendVelocity
void sendVelocity(const std::string &velNmea)
Hands over NMEA velocity message over to the send() method of manager_.
Definition: communication_core.cpp:1021
ROSaicNodeBase
This class is the base class for abstraction.
Definition: typedefs.hpp:192
Settings::tcp_ip_server
std::string tcp_ip_server
TCP IP server id.
Definition: settings.hpp:170
ConcurrentQueue::pop
void pop(T &output) noexcept
Definition: telegram.hpp:196
Settings::theta_x
double theta_x
IMU orientation x-angle.
Definition: settings.hpp:213
Settings::publish_velsensorsetup
bool publish_velsensorsetup
Whether or not to publish the VelSensorSetupMsg message.
Definition: settings.hpp:306
Settings::theta_y
double theta_y
IMU orientation y-angle.
Definition: settings.hpp:215
Settings::ant_aux1_serial_nr
std::string ant_aux1_serial_nr
Serial number of your particular Aux1 antenna.
Definition: settings.hpp:209
ATTSTD_DEV_MIN
static const int8_t ATTSTD_DEV_MIN
Definition: communication_core.cpp:50
Settings::publish_exteventinsnavcart
bool publish_exteventinsnavcart
Whether or not to publish the ExtEventINSNavCartMsg message.
Definition: settings.hpp:310
Settings::publish_gpsfix
bool publish_gpsfix
Whether or not to publish the GpsFixMsg message.
Definition: settings.hpp:318
io::CommunicationCore::processingThread_
std::thread processingThread_
Processing thread.
Definition: communication_core.hpp:164
Settings::configure_rx
bool configure_rx
Definition: settings.hpp:187
Settings::publish_gpgsa
bool publish_gpgsa
Whether or not to publish the GSA message.
Definition: settings.hpp:263
io::CommunicationCore::settings_
const Settings * settings_
Settings.
Definition: communication_core.hpp:158
Settings::publish_velcovgeodetic
bool publish_velcovgeodetic
Definition: settings.hpp:294
Settings::ptp_server_clock
bool ptp_server_clock
Wether PTP grandmaster clock shall be activated.
Definition: settings.hpp:348
Settings::tcp_port
uint32_t tcp_port
TCP port.
Definition: settings.hpp:168
Settings::publish_poscovgeodetic
bool publish_poscovgeodetic
Definition: settings.hpp:288
Settings::publish_tf_ecef
bool publish_tf_ecef
Whether or not to publish the tf of the localization.
Definition: settings.hpp:334
Settings::vsm_y
double vsm_y
INS velocity sensor lever arm y-offset.
Definition: settings.hpp:233
io::CommunicationCore::mainConnectionPort_
std::string mainConnectionPort_
Main communication port.
Definition: communication_core.hpp:182
Settings::publish_basevectorcart
bool publish_basevectorcart
Definition: settings.hpp:280
HEADING_MAX
static const int16_t HEADING_MAX
Definition: communication_core.cpp:46
Rtk::ntrip
std::vector< RtkNtrip > ntrip
Definition: settings.hpp:107
device_type::SBF_FILE
@ SBF_FILE
Definition: settings.hpp:143
InsVsm::serial_keep_open
bool serial_keep_open
Wether VSM shall be kept open om shutdown.
Definition: settings.hpp:135
io::CommunicationCore::CommunicationCore
CommunicationCore(ROSaicNodeBase *node)
Constructor of the class CommunicationCore.
Definition: communication_core.cpp:63
LEVER_ARM_MIN
static const int8_t LEVER_ARM_MIN
Definition: communication_core.cpp:45
Settings::vsm_z
double vsm_z
INS velocity sensor lever arm z-offset.
Definition: settings.hpp:235
Settings::pitch_offset
double pitch_offset
Attitude offset determination in latitudinal direction.
Definition: settings.hpp:239
string_utilities::trimDecimalPlaces
std::string trimDecimalPlaces(double num)
Trims decimal places to three.
Definition: string_utilities.cpp:190
Settings::ant_aux1_type
std::string ant_aux1_type
Definition: settings.hpp:205
Settings::publish_localization_ecef
bool publish_localization_ecef
Whether or not to publish the LocalizationMsg message.
Definition: settings.hpp:328
ROSaicNodeBase::isIns
bool isIns()
Check if Rx is INS.
Definition: typedefs.hpp:440
Settings::delta_u
float delta_u
Marker-to-ARP offset in the upward direction.
Definition: settings.hpp:199
io::CommunicationCore::node_
ROSaicNodeBase * node_
Pointer to Node.
Definition: communication_core.hpp:156
Settings::ins_use_poi
bool ins_use_poi
INS solution reference point.
Definition: settings.hpp:243
Settings::ant_serial_nr
std::string ant_serial_nr
Serial number of your particular Main antenna.
Definition: settings.hpp:207
PITCH_MAX
static const int8_t PITCH_MAX
Definition: communication_core.cpp:48
io
Definition: async_manager.hpp:83
Settings::ant_type
std::string ant_type
Definition: settings.hpp:202
Settings::publish_atteuler
bool publish_atteuler
Whether or not to publish the AttEulerMsg message.
Definition: settings.hpp:296
Settings::login_user
std::string login_user
Username for login.
Definition: settings.hpp:174
THETA_Y_MAX
static const int8_t THETA_Y_MAX
Definition: communication_core.cpp:42
InsVsm::use_stream_device
bool use_stream_device
Wether to use stream device tcp.
Definition: settings.hpp:123
Settings::publish_basevectorgeod
bool publish_basevectorgeod
Whether or not to publish the BaseVectorGeodMsg message.
Definition: settings.hpp:282
Settings::publish_diagnostics
bool publish_diagnostics
Whether or not to publish the DiagnosticArrayMsg message.
Definition: settings.hpp:322
io::CommunicationCore::udpClient_
std::unique_ptr< UdpClient > udpClient_
Definition: communication_core.hpp:172
ConcurrentQueue::push
void push(const T &input) noexcept
Definition: telegram.hpp:186
Settings::polling_period_rest
uint32_t polling_period_rest
Polling period for all other SBF blocks and NMEA messages.
Definition: settings.hpp:193
Rtk::ip_server
std::vector< RtkIpServer > ip_server
Definition: settings.hpp:108
device_type::SERIAL
@ SERIAL
Definition: settings.hpp:142
ROSaicNodeBase::hasHeading
bool hasHeading()
Check if Rx has heading.
Definition: typedefs.hpp:445
Settings::poi_z
double poi_z
INS POI offset in z-dimension.
Definition: settings.hpp:229
ANGLE_MAX
static const int16_t ANGLE_MAX
Definition: communication_core.cpp:40
Settings::custom_commands_file
std::string custom_commands_file
Custom commands file.
Definition: settings.hpp:178
Settings::publish_poscovcartesian
bool publish_poscovcartesian
Definition: settings.hpp:285
Settings::publish_insnavcart
bool publish_insnavcart
Whether or not to publish the INSNavCartMsg message.
Definition: settings.hpp:300
Settings::delta_e
float delta_e
Marker-to-ARP offset in the eastward direction.
Definition: settings.hpp:195
device_type::PCAP_FILE
@ PCAP_FILE
Definition: settings.hpp:144
io::CommunicationCore::initializeIo
bool initializeIo()
Initializes the I/O handling.
Definition: communication_core.cpp:202
log_level::ERROR
@ ERROR
Definition: typedefs.hpp:183
Settings::read_from_sbf_log
bool read_from_sbf_log
Whether or not we are reading from an SBF file.
Definition: settings.hpp:369
string_utilities::containsSpace
bool containsSpace(const std::string str)
Checks if a string contains spaces.
Definition: string_utilities.cpp:201
io::CommunicationCore::streamPort_
std::string streamPort_
Definition: communication_core.hpp:184
settings
Definition: settings_helpers.hpp:41
Settings::ins_vsm
InsVsm ins_vsm
INS VSM setting.
Definition: settings.hpp:373
Settings::ant_lever_z
double ant_lever_z
INS antenna lever arm z-offset.
Definition: settings.hpp:223
Settings::publish_gprmc
bool publish_gprmc
Whether or not to publish the RMC message.
Definition: settings.hpp:261
io::CommunicationCore::send
void send(const std::string &cmd)
Hands over to the send() method of manager_.
Definition: communication_core.cpp:1065
io::CommunicationCore::connect
void connect()
Connects the data stream.
Definition: communication_core.cpp:168
io::TelegramHandler::waitForCapabilities
void waitForCapabilities()
Waits for capabilities.
Definition: telegram_handler.hpp:151
log_level::DEBUG
@ DEBUG
Definition: typedefs.hpp:180
telegram_type::EMPTY
@ EMPTY
Definition: telegram.hpp:98
io::CommunicationCore::close
void close()
Definition: communication_core.cpp:85
io::CommunicationCore::processTelegrams
void processTelegrams()
Definition: communication_core.cpp:1053
io::CommunicationCore::telegramQueue_
TelegramQueue telegramQueue_
TelegramQueue.
Definition: communication_core.hpp:160
Settings::publish_navsatfix
bool publish_navsatfix
Whether or not to publish the NavSatFixMsg message.
Definition: settings.hpp:316
Settings::publish_tf
bool publish_tf
Whether or not to publish the tf of the localization.
Definition: settings.hpp:332
Settings::udp_unicast_ip
std::string udp_unicast_ip
UDP unicast destination ip.
Definition: settings.hpp:164
POSSTD_DEV_MIN
static const int8_t POSSTD_DEV_MIN
Definition: communication_core.cpp:52
Settings::att_std_dev
float att_std_dev
Attitude deviation mask.
Definition: settings.hpp:247
io::CommunicationCore::running_
std::atomic< bool > running_
Indicator for threads to run.
Definition: communication_core.hpp:179
Settings::publish_measepoch
bool publish_measepoch
Whether or not to publish the MeasEpoch message.
Definition: settings.hpp:267
Settings::publish_exteventinsnavgeod
bool publish_exteventinsnavgeod
Whether or not to publish the ExtEventINSNavGeodMsg message.
Definition: settings.hpp:308
ATTSTD_DEV_MAX
static const int8_t ATTSTD_DEV_MAX
Definition: communication_core.cpp:51
Settings::ant_lever_x
double ant_lever_x
INS antenna lever arm x-offset.
Definition: settings.hpp:219
Settings::publish_extsensormeas
bool publish_extsensormeas
Whether or not to publish the ExtSensorMeasMsg message.
Definition: settings.hpp:312
io::TelegramHandler::waitForResponse
void waitForResponse()
Waits for response.
Definition: telegram_handler.hpp:148
io::CommunicationCore::resetMainConnection
std::string resetMainConnection()
Reset main connection so it can receive commands.
Definition: communication_core.cpp:1037
Settings::device
std::string device
Device.
Definition: settings.hpp:154
io::CommunicationCore::~CommunicationCore
~CommunicationCore()
Default destructor of the class CommunicationCore.
Definition: communication_core.cpp:73
HEADING_MIN
static const int16_t HEADING_MIN
Definition: communication_core.cpp:47
Settings::publish_insnavgeod
bool publish_insnavgeod
Whether or not to publish the INSNavGeodMsg message.
Definition: settings.hpp:302
Settings::rtk
Rtk rtk
RTK corrections settings.
Definition: settings.hpp:251
io::TelegramHandler::handleTelegram
void handleTelegram(const std::shared_ptr< Telegram > &telegram)
Called every time a telegram is received.
Definition: telegram_handler.cpp:41
Settings::septentrio_receiver_type
std::string septentrio_receiver_type
Septentrio receiver type, either "gnss" or "ins".
Definition: settings.hpp:340
io::CommunicationCore::manager_
std::unique_ptr< AsyncManagerBase > manager_
Definition: communication_core.hpp:169
log_level::INFO
@ INFO
Definition: typedefs.hpp:181
LEVER_ARM_MAX
static const int8_t LEVER_ARM_MAX
Definition: communication_core.cpp:44
io::CommunicationCore::telegramHandler_
TelegramHandler telegramHandler_
TelegramHandler.
Definition: communication_core.hpp:162
Settings::read_from_pcap
bool read_from_pcap
Whether or not we are reading from a PCAP file.
Definition: settings.hpp:371
Settings::publish_gpgsv
bool publish_gpgsv
Whether or not to publish the GSV message.
Definition: settings.hpp:265
InsVsm::ip_server_port
uint32_t ip_server_port
VSM tcp port.
Definition: settings.hpp:127
Settings::ant_lever_y
double ant_lever_y
INS antenna lever arm y-offset.
Definition: settings.hpp:221
io::CommunicationCore::initializedIo_
bool initializedIo_
Whether connecting was successful.
Definition: communication_core.hpp:166


septentrio_gnss_driver
Author(s): Tibor Dome, Thomas Emter
autogenerated on Sat May 10 2025 03:03:10