Goby v2
message_algorithms.cpp
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #include <boost/foreach.hpp>
24 
25 #include "goby/acomms/dccl.h"
26 #include "message.h"
27 #include "message_algorithms.h"
28 #include "message_val.h"
29 
30 #include "goby/util/as.h"
31 
32 goby::transitional::DCCLAlgorithmPerformer* goby::transitional::DCCLAlgorithmPerformer::inst_ = 0;
33 
34 // singleton class, use this to get pointer
36 goby::transitional::DCCLAlgorithmPerformer::getInstance()
37 {
38  if (!inst_)
39  inst_ = new DCCLAlgorithmPerformer();
40 
41  return (inst_);
42 }
43 
44 void goby::transitional::DCCLAlgorithmPerformer::deleteInstance() { delete inst_; }
45 
46 void goby::transitional::DCCLAlgorithmPerformer::algorithm(
47  DCCLMessageVal& in, unsigned array_index, const std::string& algorithm,
48  const std::map<std::string, std::vector<DCCLMessageVal> >& vals)
49 {
50  if (in.empty())
51  return;
52 
53  // algo_name:ref_variable_name1:ref_variable_name2...
54 
55  std::vector<std::string> ref_vars;
56  std::string algorithm_deblanked = boost::erase_all_copy(algorithm, " ");
57  boost::split(ref_vars, algorithm_deblanked, boost::is_any_of(":"));
58 
59  std::string alg;
60  std::vector<DCCLMessageVal> tied_vals;
61 
62  for (std::vector<std::string>::size_type i = 1, n = ref_vars.size(); i < n; ++i)
63  {
64  std::map<std::string, std::vector<DCCLMessageVal> >::const_iterator it =
65  vals.find(ref_vars[i]);
66  if (it != vals.end())
67  {
68  if (array_index < it->second.size())
69  tied_vals.push_back(it->second[array_index]);
70  else
71  tied_vals.push_back(it->second[0]);
72  }
73  }
74 
75  if (ref_vars.size() > 0)
76  alg = ref_vars[0];
77 
78  run_algorithm(alg, in, tied_vals);
79 }
80 
81 void goby::transitional::DCCLAlgorithmPerformer::run_algorithm(
82  const std::string& algorithm, DCCLMessageVal& in, const std::vector<DCCLMessageVal>& ref)
83 {
84  // short form for simple algorithms
85  if (adv_map1_.count(algorithm))
86  {
87  adv_map1_.find(algorithm)->second(in);
88  }
89  // longer form for more demanding algorithms
90  else if (adv_map2_.count(algorithm))
91  {
92  adv_map2_.find(algorithm)->second(in, ref);
93  }
94 }
95 
96 // check validity of algorithm name and references
97 void goby::transitional::DCCLAlgorithmPerformer::check_algorithm(const std::string& alg,
98  const DCCLMessage& msg)
99 {
100  if (alg.empty())
101  return;
102 
103  std::vector<std::string> ref_vars;
104  std::string algorithm_deblanked = boost::erase_all_copy(alg, " ");
105  boost::split(ref_vars, algorithm_deblanked, boost::is_any_of(":"));
106 
107  // check if the algorithm exists
108  // but ignore if no algorithms loaded (to use for testing tools)
109  if ((adv_map1_.size() || adv_map2_.size()) && !adv_map1_.count(ref_vars.at(0)) &&
110  !adv_map2_.count(ref_vars.at(0)))
111  throw(goby::acomms::DCCLException("unknown algorithm defined: " + ref_vars.at(0)));
112 
113  for (std::vector<std::string>::size_type i = 1, n = ref_vars.size(); i < n; ++i)
114  {
115  bool ref_found = false;
116  BOOST_FOREACH (const boost::shared_ptr<DCCLMessageVar> mv, msg.header_const())
117  {
118  if (ref_vars[i] == mv->name())
119  {
120  ref_found = true;
121  break;
122  }
123  }
124 
125  BOOST_FOREACH (const boost::shared_ptr<DCCLMessageVar> mv, msg.layout_const())
126  {
127  if (ref_vars[i] == mv->name())
128  {
129  ref_found = true;
130  break;
131  }
132  }
133 
134  if (!ref_found)
135  throw(goby::acomms::DCCLException(
136  std::string("no such reference message variable " + ref_vars.at(i) +
137  " used in algorithm: " + ref_vars.at(0))));
138  }
139 }