master.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  *
22  * Authors: Christoph Rösmann
23  *********************************************************************/
24 
25 #include <corbo-master/master.h>
26 
29 #include <corbo-core/global.h>
30 
31 #include <fstream>
32 #include <memory>
33 #include <string>
34 
35 namespace corbo {
36 
37 void Master::start(const std::string& server_address, bool blocking)
38 {
40 
41  grpc::ServerBuilder builder;
42 
43  // Listen on the given address without any authentication mechanism.
44  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
45 
46  // Create main service
47  builder.RegisterService(this);
48 
49  _server = builder.BuildAndStart();
50  if (_server)
51  {
52  PRINT_INFO("RpcServer listening on " << server_address);
53  if (blocking) _server->Wait();
54  }
55  else
56  {
57  PRINT_ERROR("RpcServer failed");
58  }
59 }
60 
61 void Master::setDefault()
62 {
63  PRINT_DEBUG_NAMED("Initializing default environment.");
64 
65  // controller
67  ControllerInterface::Ptr controller = ControllerFactory::instance().create("PidController");
68  if (controller) _environment.setController(controller);
69 
70  // observer
72  ObserverInterface::Ptr observer = ObserverFactory::instance().create("NoObserver");
73  if (observer) _environment.setObserver(observer);
74 
75  corbo::SerialIntegratorSystem::Ptr system = std::make_shared<corbo::SerialIntegratorSystem>();
76  corbo::FullStateSystemOutput::Ptr output = std::make_shared<corbo::FirstStateSystemOutput>();
77  corbo::PlantInterface::Ptr plant = std::make_shared<corbo::SimulatedPlant>(system, output);
78  if (plant) _environment.setPlant(plant);
79 
80  // task
82  _task = TaskFactory::instance().create("ClosedLoopControlTask");
83 }
84 
85 bool Master::loadFromFile(const std::string& filename)
86 {
87  if (filename.empty()) return false;
88 
89  corbo::messages::corboParameters msg;
90 
91  std::ifstream file(filename);
92 
93  if (!file.is_open())
94  {
95  return false;
96  }
97 
98  if (!msg.ParsePartialFromIstream(&file))
99  {
100  return false;
101  }
102 
103  std::stringstream issues;
104  if (!setcorboMessage(msg, &issues))
105  {
106  PRINT_ERROR_NAMED(issues.str());
107  return false;
108  }
109 
110  return true;
111 }
112 
113 bool Master::setcorboMessage(const messages::corboParameters& msg, std::stringstream* issues)
114 {
115  bool result = setPlant(msg.plant(), issues);
116  PRINT_ERROR_COND_NAMED(!result, "setPlant failed.");
117 
118  result &= setController(msg.controller(), issues);
119  PRINT_ERROR_COND_NAMED(!result, "setController failed.");
120 
121  result &= setObserver(msg.observer(), issues);
122  PRINT_ERROR_COND_NAMED(!result, "setObserver failed.");
123 
124  result &= setTask(msg.task(), issues);
125  PRINT_ERROR_COND_NAMED(!result, "setTask failed.");
126 
127  return result;
128 }
129 
130 bool Master::setPlant(const messages::Plant& msg, std::stringstream* issues)
131 {
132  // if (!_environment.getPlant()) return false; // grpc::Status::CANCELLED;
133 
134  if (msg.plant_case() == corbo::messages::Plant::PLANT_NOT_SET)
135  {
136  if (issues) *issues << "No plant selected." << std::endl;
137  return false;
138  }
139  std::string plant_type;
140  if (util::get_oneof_field_type(msg, "plant", plant_type, false))
141  {
142  PlantInterface::Ptr plant = PlantFactory::instance().create(plant_type, false);
143  if (!plant)
144  {
145  // also check if we have nested, isolated one-of messages
146  util::get_oneof_field_type_expand_isolated(msg, "plant", plant_type, false);
147  plant = PlantFactory::instance().create(plant_type);
148  }
149 
150  if (plant)
151  {
152  plant->fromMessage(msg, issues);
153  _environment.setPlant(plant);
154  return issues ? issues->str().empty() : true; // TODO(roesmann) correct return value
155  }
156  if (issues) *issues << "Plant type '" + plant_type + "' not found." << std::endl;
157  }
158  else if (issues)
159  *issues << "Cannot determine type of specified plant. Protobuf error." << std::endl;
160 
161  return false;
162 }
163 
164 bool Master::setController(const messages::Controller& msg, std::stringstream* issues)
165 {
166  // if (!_environment.getController()) return false; // grpc::Status::CANCELLED;
167 
168  if (msg.controller_case() == corbo::messages::Controller::CONTROLLER_NOT_SET)
169  {
170  if (issues) *issues << "No controller selected." << std::endl;
171  return false;
172  }
173  std::string controller_type;
174  if (util::get_oneof_field_type(msg, "controller", controller_type, false))
175  {
176  ControllerInterface::Ptr controller = ControllerFactory::instance().create(controller_type, false);
177  if (!controller)
178  {
179  // also check if we have nested, isolated one-of messages
180  util::get_oneof_field_type_expand_isolated(msg, "controller", controller_type, false);
181  controller = ControllerFactory::instance().create(controller_type);
182  }
183 
184  if (controller)
185  {
186  controller->fromMessage(msg, issues);
187  _environment.setController(controller);
188  return issues ? issues->str().empty() : true; // TODO(roesmann) correct return value
189  }
190  if (issues) *issues << "Controller type '" + controller_type + "' not found." << std::endl;
191  }
192  else if (issues)
193  *issues << "Cannot determine type of specified controller. Protobuf error." << std::endl;
194 
195  return false;
196 }
197 
198 bool Master::setObserver(const messages::Observer& msg, std::stringstream* issues)
199 {
200  // if (!_environment.getObserver()) return false; // grpc::Status::CANCELLED;
201 
202  if (msg.observer_case() == corbo::messages::Observer::OBSERVER_NOT_SET)
203  {
204  if (issues) *issues << "No observer selected." << std::endl;
205  return false;
206  }
207  std::string observer_type;
208  if (util::get_oneof_field_type(msg, "observer", observer_type, false))
209  {
210  ObserverInterface::Ptr observer = ObserverFactory::instance().create(observer_type, false);
211  if (!observer)
212  {
213  // also check if we have nested, isolated one-of messages
214  util::get_oneof_field_type_expand_isolated(msg, "observer", observer_type, false);
215  observer = ObserverFactory::instance().create(observer_type);
216  }
217 
218  if (observer)
219  {
220  observer->fromMessage(msg, issues);
221  _environment.setObserver(observer);
222  return issues ? issues->str().empty() : true; // TODO(roesmann) correct return value
223  }
224  if (issues) *issues << "Observer type '" + observer_type + "' not found." << std::endl;
225  }
226  else if (issues)
227  *issues << "Cannot determine type of specified observer. Protobuf error." << std::endl;
228 
229  return false;
230 }
231 
232 bool Master::setTask(const messages::Task& msg, std::stringstream* issues)
233 {
234  if (msg.task_case() == corbo::messages::Task::TASK_NOT_SET)
235  {
236  if (issues) *issues << "No task selected." << std::endl;
237  return false;
238  }
239  std::string task_type;
240  if (util::get_oneof_field_type(msg, "task", task_type, false))
241  {
242  _task = TaskFactory::instance().create(task_type, false);
243  if (!_task)
244  {
245  // also check if we have nested, isolated one-of messages
246  util::get_oneof_field_type_expand_isolated(msg, "task", task_type, false);
247  _task = TaskFactory::instance().create(task_type);
248  }
249 
250  if (_task)
251  {
252  _task->fromMessage(msg, issues);
253  return issues ? issues->str().empty() : true; // TODO(roesmann) correct return value
254  }
255  if (issues) *issues << "Task type '" + task_type + "' not found." << std::endl;
256  }
257  else if (issues)
258  *issues << "Cannot determine type of specified task. Protobuf error." << std::endl;
259 
260  return false;
261 }
262 
263 grpc::Status Master::setPlant(grpc::ServerContext* context, const corbo::messages::Plant* request, corbo::messages::Status* response)
264 {
265  std::stringstream issues;
266  if (setPlant(*request, &issues))
267  {
268  response->set_ok(true);
269  }
270  else
271  {
272  response->set_ok(false);
273  response->set_text(issues.str());
274  }
275  return grpc::Status::OK;
276 }
277 
278 grpc::Status Master::getPlant(grpc::ServerContext* context, const corbo::messages::Void* request, corbo::messages::Plant* response)
279 {
280  if (!_environment.getPlant()) return grpc::Status::CANCELLED;
281  _environment.getPlant()->toMessage(*response);
282  return grpc::Status::OK;
283 }
284 
285 grpc::Status Master::setController(grpc::ServerContext* context, const corbo::messages::Controller* request, corbo::messages::Status* response)
286 {
287  std::stringstream issues;
288  if (setController(*request, &issues))
289  {
290  response->set_ok(true);
291  }
292  else
293  {
294  response->set_ok(false);
295  response->set_text(issues.str());
296  }
297  return grpc::Status::OK;
298 }
299 
300 grpc::Status Master::getController(grpc::ServerContext* context, const corbo::messages::Void* request, corbo::messages::Controller* response)
301 {
302  if (!_environment.getController()) return grpc::Status::CANCELLED;
303  _environment.getController()->toMessage(*response);
304  return grpc::Status::OK;
305 }
306 
307 grpc::Status Master::setObserver(grpc::ServerContext* context, const corbo::messages::Observer* request, corbo::messages::Status* response)
308 {
309  std::stringstream issues;
310  if (setObserver(*request, &issues))
311  {
312  response->set_ok(true);
313  }
314  else
315  {
316  response->set_ok(false);
317  response->set_text(issues.str());
318  }
319  return grpc::Status::OK;
320 }
321 
322 grpc::Status Master::getObserver(grpc::ServerContext* context, const corbo::messages::Void* request, corbo::messages::Observer* response)
323 {
324  if (!_environment.getObserver()) return grpc::Status::CANCELLED;
325  _environment.getObserver()->toMessage(*response);
326  return grpc::Status::OK;
327 }
328 
329 grpc::Status Master::setTask(grpc::ServerContext* context, const corbo::messages::Task* request, corbo::messages::Status* response)
330 {
331  std::stringstream issues;
332  if (setTask(*request, &issues))
333  {
334  response->set_ok(true);
335  }
336  else
337  {
338  response->set_ok(false);
339  response->set_text(issues.str());
340  }
341  return grpc::Status::OK;
342 }
343 
344 grpc::Status Master::getTask(grpc::ServerContext* context, const corbo::messages::Void* request, corbo::messages::Task* response)
345 {
346  if (!_task) return grpc::Status::CANCELLED;
347  _task->toMessage(*response);
348  return grpc::Status::OK;
349 }
350 
351 grpc::Status Master::getAvailableSignals(grpc::ServerContext* context, const corbo::messages::Void* request,
352  grpc::ServerWriter<messages::Signal>* response_stream)
353 {
354  if (_task)
355  {
356  SignalTargetRPC::Ptr signal_target = std::make_shared<SignalTargetRPC>(response_stream);
357  _task->getAvailableSignals(_environment, *signal_target);
358  }
359  return grpc::Status::OK;
360 }
361 
362 grpc::Status Master::performTask(grpc::ServerContext* context, const corbo::messages::Void* request,
363  grpc::ServerWriter<messages::Signal>* response_stream)
364 {
365  setOk(true); // reset global ok-state
366  std::string err_msg;
367  if (_task)
368  {
369  SignalTargetRPC::Ptr signal_target = std::make_shared<SignalTargetRPC>(response_stream);
370  _task->performTask(_environment, signal_target.get(), &err_msg);
371  }
372 
373  if (!err_msg.empty())
374  {
375  return grpc::Status(grpc::StatusCode::ABORTED, err_msg);
376  }
377 
378  return grpc::Status::OK;
379 }
380 
381 grpc::Status Master::verifyConfig(grpc::ServerContext* context, const corbo::messages::Void* request, corbo::messages::Status* response)
382 {
383  if (_task)
384  {
385  std::string result;
386  response->set_ok(_task->verify(_environment, &result));
387  response->set_text(result);
388  }
389  else
390  {
391  response->set_text("No task selected!");
392  }
393  return grpc::Status::OK;
394 }
395 
396 grpc::Status Master::ping(grpc::ServerContext* context, const corbo::messages::Void* request, corbo::messages::Status* response)
397 {
398  response->set_text("got it");
399  response->set_ok(true);
400  return grpc::Status::OK;
401 }
402 
403 grpc::Status Master::stop(grpc::ServerContext* context, const corbo::messages::Void* request, corbo::messages::Void* response)
404 {
405  setOk(false); // set global ok flag which should be checked frequently by the current task
406  return grpc::Status::OK;
407 }
408 
409 } // namespace corbo
corbo::Environment::getObserver
const ObserverInterface::Ptr & getObserver() const
Read access to the underlying observer.
Definition: environment.h:115
global.h
PRINT_ERROR_NAMED
#define PRINT_ERROR_NAMED(msg)
Definition: console.h:260
corbo::Master::_server
std::unique_ptr< grpc::Server > _server
Definition: master.h:179
corbo::Master::_task
TaskInterface::Ptr _task
Definition: master.h:177
corbo::Master::loadFromFile
bool loadFromFile(const std::string &filename)
Definition: master.cpp:107
corbo::Environment::setPlant
void setPlant(PlantInterface::Ptr plant)
Set plant.
Definition: environment.cpp:66
corbo
Definition: communication/include/corbo-communication/utilities.h:37
PRINT_ERROR_COND_NAMED
#define PRINT_ERROR_COND_NAMED(cond, msg)
Definition: console.h:262
corbo::Master::_environment
Environment _environment
Definition: master.h:176
corbo::Master::ping
grpc::Status ping(grpc::ServerContext *context, const corbo::messages::Void *request, corbo::messages::Status *response) override
Send and receive dummy message in order to check the connectivity between master and client.
Definition: master.cpp:418
corbo::Environment::hasController
bool hasController() const
Check if a controller has been specified.
Definition: environment.h:104
corbo::Master::getTask
grpc::Status getTask(grpc::ServerContext *context, const corbo::messages::Void *request, corbo::messages::Task *response) override
Get current task configuration.
Definition: master.cpp:366
corbo::Master::getPlant
grpc::Status getPlant(grpc::ServerContext *context, const corbo::messages::Void *request, corbo::messages::Plant *response) override
Get current plant configuration.
Definition: master.cpp:300
corbo::Master::getController
grpc::Status getController(grpc::ServerContext *context, const corbo::messages::Void *request, corbo::messages::Controller *response) override
Get current controller configuration.
Definition: master.cpp:322
corbo::setOk
void setOk(bool ok)
Change the current program state to ok or request the termination of the current action.
Definition: global.cpp:55
corbo::Master::verifyConfig
grpc::Status verifyConfig(grpc::ServerContext *context, const corbo::messages::Void *request, corbo::messages::Status *response) override
Check if the current configuration seems to be valid (refer to TaskInterface::verify())
Definition: master.cpp:403
corbo::Master::setTask
bool setTask(const corbo::messages::Task &msg, std::stringstream *issues=nullptr)
corbo::Environment::setController
void setController(ControllerInterface::Ptr controller)
Set controller.
Definition: environment.cpp:62
corbo::Master::setcorboMessage
bool setcorboMessage(const corbo::messages::corboParameters &msg, std::stringstream *issues)
Definition: master.cpp:135
corbo::Environment::getPlant
const PlantInterface::Ptr & getPlant() const
Read access to the underlying plant.
Definition: environment.h:119
corbo::ObserverInterface::Ptr
std::shared_ptr< ObserverInterface > Ptr
Definition: observer_interface.h:105
PRINT_DEBUG_NAMED
#define PRINT_DEBUG_NAMED(msg)
Definition: console.h:245
corbo::Factory::instance
static Factory & instance()
< Retrieve static instance of the factory
Definition: factory.h:116
relicense.filename
filename
Definition: relicense.py:57
corbo::Master::start
void start(const std::string &server_address, bool blocking=true)
Start master server (blocking call)
Definition: master.cpp:59
Eigen::LevenbergMarquardtSpace::Status
Status
Definition: LevenbergMarquardt/LevenbergMarquardt.h:25
corbo::Master::setPlant
bool setPlant(const messages::Plant &msg, std::stringstream *issues=nullptr)
Definition: master.cpp:152
corbo::Master::stop
grpc::Status stop(grpc::ServerContext *context, const corbo::messages::Void *request, corbo::messages::Void *response) override
Execution stop of the current task requested (setting global ok() variable to false,...
Definition: master.cpp:425
corbo::Master::setObserver
bool setObserver(const corbo::messages::Observer &msg, std::stringstream *issues=nullptr)
corbo::Master::setDefault
void setDefault()
Restore default master settings.
Definition: master.cpp:83
corbo::Master::getAvailableSignals
grpc::Status getAvailableSignals(grpc::ServerContext *context, const corbo::messages::Void *request, grpc::ServerWriter< corbo::messages::Signal > *response_stream) override
Retrieve available signals from task (and included modules)
Definition: master.cpp:373
signal_target_rpc.h
corbo::SystemDynamicsInterface::Ptr
std::shared_ptr< SystemDynamicsInterface > Ptr
Definition: system_dynamics_interface.h:91
corbo::ControllerInterface::Ptr
std::shared_ptr< ControllerInterface > Ptr
Definition: controller_interface.h:105
corbo::Environment::setObserver
void setObserver(ObserverInterface::Ptr observer)
Set observer.
Definition: environment.cpp:64
corbo::Master::performTask
grpc::Status performTask(grpc::ServerContext *context, const corbo::messages::Void *request, grpc::ServerWriter< corbo::messages::Signal > *response_stream) override
Perform the current task and broadcast stream of signals.
Definition: master.cpp:384
corbo::Environment::hasObserver
bool hasObserver() const
Check if an observer has been specified.
Definition: environment.h:106
utilities.h
corbo::Factory::create
std::shared_ptr< Derived > create(const std::string &name, bool print_error=true) const
Create a shared instance of the desired object.
Definition: factory.h:137
master.h
corbo::Master::setController
bool setController(const corbo::messages::Controller &msg, std::stringstream *issues=nullptr)
corbo::Environment::getController
const ControllerInterface::Ptr & getController() const
Read access to the underlying controller.
Definition: environment.h:111
corbo::SystemOutputInterface::Ptr
std::shared_ptr< SystemOutputInterface > Ptr
Definition: output_function_interface.h:109
corbo::Environment::hasPlant
bool hasPlant() const
Check if a plant has been specified.
Definition: environment.h:108
corbo::Factory::printObjects
void printObjects() const
Print registered object names to console.
Definition: factory.h:167
PRINT_INFO
#define PRINT_INFO(msg)
Print msg-stream.
Definition: console.h:117
corbo::Master::getObserver
grpc::Status getObserver(grpc::ServerContext *context, const corbo::messages::Void *request, corbo::messages::Observer *response) override
Get current observer configuration.
Definition: master.cpp:344
PRINT_ERROR
#define PRINT_ERROR(msg)
Print msg-stream as error msg.
Definition: console.h:173
corbo::PlantInterface::Ptr
std::shared_ptr< PlantInterface > Ptr
Definition: plant_interface.h:101


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Wed Mar 2 2022 00:05:55