param_manager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Daniel Koch and James Jackson, BYU MAGICC Lab.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * * Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
38 #include <ros/ros.h>
39 #include <yaml-cpp/yaml.h>
40 
41 #include <fstream>
42 
43 namespace mavrosflight
44 {
45 
47  comm_(comm),
48  unsaved_changes_(false),
49  write_request_in_progress_(false),
50  first_param_received_(false),
51  received_count_(0),
52  got_all_params_(false),
53  param_set_in_progress_(false)
54 {
56 
59  false, /* not oneshot */
60  false /* not autostart */);
61 }
62 
64 {
66  {
67  delete[] received_;
68  }
69 }
70 
71 void ParamManager::handle_mavlink_message(const mavlink_message_t &msg)
72 {
73  switch (msg.msgid)
74  {
77  break;
80  break;
81  }
82 }
83 
85 {
86  return unsaved_changes_;
87 }
88 
89 bool ParamManager::get_param_value(std::string name, double *value)
90 {
91  if (is_param_id(name))
92  {
93  *value = params_[name].getValue();
94  return true;
95  }
96  else
97  {
98  *value = 0.0;
99  return false;
100  }
101 }
102 
103 bool ParamManager::set_param_value(std::string name, double value)
104 {
105  if (is_param_id(name))
106  {
107  mavlink_message_t msg;
108  params_[name].requestSet(value, &msg);
109 
110  param_set_queue_.push_back(msg);
112  {
114  param_set_in_progress_ = true;
115  }
116 
117  return true;
118  }
119  else
120  {
121  return false;
122  }
123 }
124 
126 {
128  {
129  mavlink_message_t msg;
130  uint8_t sysid = 1;
131  uint8_t compid = 1;
133  comm_->send_message(msg);
134 
136  return true;
137  }
138  else
139  {
140  return false;
141  }
142 }
143 
145 {
146  if (listener == NULL)
147  return;
148 
149  bool already_registered = false;
150  for (int i = 0; i < listeners_.size(); i++)
151  {
152  if (listener == listeners_[i])
153  {
154  already_registered = true;
155  break;
156  }
157  }
158 
159  if (!already_registered)
160  listeners_.push_back(listener);
161 }
162 
164 {
165  if (listener == NULL)
166  return;
167 
168  for (int i = 0; i < listeners_.size(); i++)
169  {
170  if (listener == listeners_[i])
171  {
172  listeners_.erase(listeners_.begin() + i);
173  i--;
174  }
175  }
176 }
177 
178 bool ParamManager::save_to_file(std::string filename)
179 {
180  // build YAML document
181  YAML::Emitter yaml;
182  yaml << YAML::BeginSeq;
183  std::map<std::string, Param>::iterator it;
184  for (it = params_.begin(); it != params_.end(); it++)
185  {
186  yaml << YAML::Flow;
187  yaml << YAML::BeginMap;
188  yaml << YAML::Key << "name" << YAML::Value << it->second.getName();
189  yaml << YAML::Key << "type" << YAML::Value << (int) it->second.getType();
190  yaml << YAML::Key << "value" << YAML::Value << it->second.getValue();
191  yaml << YAML::EndMap;
192  }
193  yaml << YAML::EndSeq;
194 
195  // write to file
196  try
197  {
198  std::ofstream fout;
199  fout.open(filename.c_str());
200  fout << yaml.c_str();
201  fout.close();
202  }
203  catch (...)
204  {
205  return false;
206  }
207 
208  return true;
209 }
210 
211 bool ParamManager::load_from_file(std::string filename)
212 {
213  try
214  {
215  YAML::Node root = YAML::LoadFile(filename);
216  assert(root.IsSequence());
217 
218  for (int i = 0; i < root.size(); i++)
219  {
220  if (root[i].IsMap() && root[i]["name"] && root[i]["type"] && root[i]["value"])
221  {
222  if (is_param_id(root[i]["name"].as<std::string>()))
223  {
224  Param param = params_.find(root[i]["name"].as<std::string>())->second;
225  if ((MAV_PARAM_TYPE) root[i]["type"].as<int>() == param.getType())
226  {
227  set_param_value(root[i]["name"].as<std::string>(), root[i]["value"].as<double>());
228  }
229  }
230  }
231  }
232 
233  return true;
234  }
235  catch (...)
236  {
237  return false;
238  }
239 }
240 
242 {
244  {
246  }
247  else
248  {
249  for (size_t i = 0; i < num_params_; i++)
250  {
251  if (!received_[i])
252  {
253  request_param(i);
254  }
255  }
256  }
257 }
258 
260 {
261  mavlink_message_t param_list_msg;
262  mavlink_msg_param_request_list_pack(1, 50, &param_list_msg, 1, MAV_COMP_ID_ALL);
263  comm_->send_message(param_list_msg);
264 }
265 
267 {
268  mavlink_message_t param_request_msg;
270  mavlink_msg_param_request_read_pack(1, 50, &param_request_msg, 1, MAV_COMP_ID_ALL, empty, (int16_t) index);
271  comm_->send_message(param_request_msg);
272 }
273 
274 void ParamManager::handle_param_value_msg(const mavlink_message_t &msg)
275 {
277  mavlink_msg_param_value_decode(&msg, &param);
278 
280  {
281  first_param_received_ = true;
282  num_params_ = param.param_count;
283  received_ = new bool[num_params_];
284  for (int i = 0; i < num_params_; i++)
285  {
286  received_[i] = false;
287  }
288  }
289 
290  // ensure null termination of name
294 
295  std::string name(c_name);
296 
297  if (!is_param_id(name)) // if we haven't received this param before, add it
298  {
299  params_[name] = Param(param);
300  received_[param.param_index] = true;
301 
302  // increase the param count
303  received_count_++;
305  {
306  got_all_params_ = true;
307  }
308 
309  for (int i = 0; i < listeners_.size(); i++)
310  listeners_[i]->on_new_param_received(name, params_[name].getValue());
311  }
312  else // otherwise check if we have new unsaved changes as a result of a param set request
313  {
314  if (params_[name].handleUpdate(param))
315  {
316  unsaved_changes_ = true;
317  for (int i = 0; i < listeners_.size(); i++)
318  {
319  listeners_[i]->on_param_value_updated(name, params_[name].getValue());
320  listeners_[i]->on_params_saved_change(unsaved_changes_);
321  }
322  }
323  }
324 }
325 
326 void ParamManager::handle_command_ack_msg(const mavlink_message_t &msg)
327 {
329  {
332 
334  {
336  if(ack.success == ROSFLIGHT_CMD_SUCCESS)
337  {
338  ROS_INFO("Param write succeeded");
339  unsaved_changes_ = false;
340 
341  for (int i = 0; i < listeners_.size(); i++)
342  listeners_[i]->on_params_saved_change(unsaved_changes_);
343  }
344  else
345  {
346  ROS_INFO("Param write failed - maybe disarm the aricraft and try again?");
348  unsaved_changes_ = true;
349  }
350  }
351  }
352 }
353 
354 bool ParamManager::is_param_id(std::string name)
355 {
356  return (params_.find(name) != params_.end());
357 }
358 
360 {
362  {
363  return num_params_;
364  }
365  else
366  {
367  return 0;
368  }
369 }
370 
372 {
373  return received_count_;
374 }
375 
377 {
378  return got_all_params_;
379 }
380 
382 {
383  if (param_set_queue_.empty())
384  {
386  param_set_in_progress_ = false;
387  }
388  else
389  {
391  param_set_queue_.pop_front();
392  }
393 }
394 
395 } // namespace mavrosflight
bool save_to_file(std::string filename)
void param_set_timer_callback(const ros::TimerEvent &event)
void register_param_listener(ParamListenerInterface *listener)
bool param(const std::string &param_name, T &param_val, const T &default_val)
std::vector< ParamListenerInterface * > listeners_
Definition: param_manager.h:92
MAV_PARAM_TYPE
Definition: common.h:508
ParamManager(MavlinkComm *const comm)
bool is_param_id(std::string name)
void stop()
virtual void handle_mavlink_message(const mavlink_message_t &msg)
The handler function for mavlink messages to be implemented by derived classes.
void start()
void register_mavlink_listener(MavlinkListenerInterface *const listener)
Register a listener for mavlink messages.
void unregister_param_listener(ParamListenerInterface *listener)
bool set_param_value(std::string name, double value)
void handle_param_value_msg(const mavlink_message_t &msg)
#define ROS_INFO(...)
bool load_from_file(std::string filename)
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
Describes an interface classes can implement to receive and handle mavlink messages.
std::map< std::string, Param > params_
Definition: param_manager.h:95
bool get_param_value(std::string name, double *value)
std::deque< mavlink_message_t > param_set_queue_
MAV_PARAM_TYPE getType() const
Definition: param.cpp:74
void handle_command_ack_msg(const mavlink_message_t &msg)
void send_message(const mavlink_message_t &msg)
Send a mavlink message.


rosflight
Author(s): Daniel Koch , James Jackson
autogenerated on Wed Jul 3 2019 20:00:13