ScenarioCli.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarXCore::core
19 * @author Cedric Seehausen (usdnr at kit dot edu)
20 * @date 2016
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25
26#include "ScenarioCli.h"
27
28#include <filesystem>
29#include <iostream>
30
42
43#include "ScenarioCliOptions.h"
44
45namespace armarx
46{
50
51 void
53 Ice::PropertiesPtr properties)
54 {
55 //this->registry = registry;
56 }
57
58 int
59 ScenarioCli::exec(const ArmarXManagerPtr& armarXManager)
60 {
61 if (options.applicationName.empty())
62 {
63 startScenario(options.command,
64 localScen,
65 options.print,
66 armarXManager->getIceManager()->getIceGridSession()->getAdmin(),
67 options.parameters);
68 }
69 else
70 {
71 ApplicationInstancePtr app = localScen->getApplicationByName(options.applicationName);
72 if (app.get() != nullptr)
73 {
74 startApplication(options.command,
75 app,
76 options.print,
77 armarXManager->getIceManager()->getIceGridSession()->getAdmin(),
78 options.parameters);
79 }
80 else
81 {
82 options.error = true;
83 optionsManager.showHelp(options,
84 "Could not find application '" + options.applicationName +
85 "' in scenario '" + localScen->getName() + "'");
86 return 0;
87 }
88 }
89
90 if (!options.print)
91 {
92 std::cout << "Finished" << std::endl;
93 }
94
95 if (!options.wait || options.print)
96 {
97 armarXManager->shutdown();
98 }
99
100 armarXManager->waitForShutdown();
101 return 0;
102 }
103
104 int
105 ScenarioCli::run(int argc, char* argv[])
106 {
107 using namespace ScenarioManager;
108 using namespace Parser;
109 using namespace Data_Structure;
110 try
111 {
113 communicator()->getProperties()->clone(), argc, argv)));
114 }
115 catch (...)
116 {
117 std::cout << "Failed to parse arguments. exiting";
118 return -1;
119 }
120 ScenarioManagerCliOptions cliOptionsManager;
121 options = cliOptionsManager.parseCmdOptions(argc, argv);
122
123
124 if (!options.parameters.empty())
125 {
126 std::cout << "Additional command line parameters are: " << options.parameters
127 << std::endl;
128 }
129
130 //Handle help | error of parsing
131 if (options.showHelp || options.error)
132 {
133 if (options.error)
134 {
135 cliOptionsManager.showHelp(options, "Could not parse input parameters");
136 return 0;
137 }
138 cliOptionsManager.showHelp(options);
139 return 0;
140 }
141
142 //capture edge cases
143 if (options.print && options.command != "start")
144 {
145 cliOptionsManager.showHelp(options,
146 "Print is only a valid option for the start command");
147 return 0;
148 }
149 else if (options.wait && (options.command == "list" || options.command == "status"))
150 {
151 cliOptionsManager.showHelp(options, "Wait is not valid for the list or status command");
152 return 0;
153 }
154
155 PackageBuilder builder;
156
157 //Handle list
158 if (options.command.compare("list") == 0)
159 {
160 std::cout << "Listing all Scenarios out of default Packages" << std::endl;
161 for (auto package : getArmarXPackageNames())
162 {
163 std::cout << "Scenarios in " << package << ":" << std::endl;
164 PackagePtr currentPackage = builder.parsePackage(package);
165 if (currentPackage.get() == nullptr)
166 {
167 std::cout << "Package " << package
168 << " is listed in default packages, but could not be found"
169 << std::endl
170 << std::endl
171 << std::endl;
172 continue;
173 }
174 for (auto scenario : *(currentPackage->getScenarios()))
175 {
176 std::cout << scenario->getName() << std::endl;
177 }
178 std::cout << std::endl << std::endl;
179 }
180 return 0;
181 }
182
183 std::string packageName = options.packageName;
184 std::string scenarioName =
186
187 if (options.packageName.empty())
188 {
189 if (std::filesystem::is_regular_file(std::filesystem::path(options.scxPath)) ||
190 std::filesystem::is_directory(std::filesystem::path(options.scxPath)))
191 {
192 XMLScenarioParser parser;
193 std::string filePackageName;
194 if (std::filesystem::is_regular_file(std::filesystem::path(options.scxPath)))
195 {
196 filePackageName = parser.getPackageNameFromScx(options.scxPath);
197 }
198 else
199 {
200 filePackageName =
201 parser.getPackageNameFromScx((std::filesystem::path(options.scxPath) /
202 std::filesystem::path(scenarioName + ".scx"))
203 .string());
204 }
205
206 if (filePackageName != "")
207 {
208 packageName = filePackageName;
209 }
210 else
211 {
212 packageName = packageChoosingDialog(scenarioName);
213 if (packageName.empty())
214 {
215 options.error = true;
216 cliOptionsManager.showHelp(options,
217 "Could not find any package for " +
218 options.scxPath +
219 ". Please add a PackageName or Add the "
220 "PackageName to your default config.");
221 return 0;
222 }
223 }
224 }
225 else
226 {
227 packageName = packageChoosingDialog(scenarioName);
228 if (packageName.empty())
229 {
230 options.error = true;
231 cliOptionsManager.showHelp(options,
232 "Could not find any package for " + options.scxPath +
233 ". Please add a PackageName or Add the "
234 "PackageName to your default config.");
235 return 0;
236 }
237 }
238 }
239
240
241 if (scenarioName.empty())
242 {
243 options.error = true;
244 cliOptionsManager.showHelp(options,
245 "Could not find Scenario " + options.scxPath +
246 " in Package " + packageName);
247 return 0;
248 }
249
250 PackagePtr package;
251 ScenarioPtr scenario;
252
253 CMakePackageFinder finder(packageName);
254 if (!finder.packageFound())
255 {
256 options.error = true;
257 cliOptionsManager.showHelp(
258 options, "CMakePackageFinder could not find package '" + packageName + "'");
259 return 0;
260 }
261
262 XMLScenarioParser parser;
263 std::vector<std::string> scenarios =
264 parser.getScenariosFromFolder(finder.getScenariosDir());
265
266 for (auto scen : scenarios)
267 {
268 auto sFolderPos = scen.rfind("/");
269 if ((sFolderPos == std::string::npos && scen == scenarioName) ||
270 (sFolderPos != std::string::npos && scen.substr(sFolderPos + 1) == scenarioName))
271 {
272 package = builder.parsePackage(packageName,
273 StringList{scen + "::Package::" + packageName});
274 break;
275 }
276 }
277
278 if (package.get() == nullptr)
279 {
280 cliOptionsManager.showHelp(options, "Failed to parse package " + packageName);
281 return 0;
282 }
283
284 scenario = package->getScenarioByName(scenarioName);
285
286 if (scenario.get() == nullptr)
287 {
288 options.error = true;
289 cliOptionsManager.showHelp(options,
290 "Could not find Scenario " + scenarioName + " in Package " +
291 package->getName());
292 return 0;
293 }
294
295 if (options.command == "generate")
296 {
297 Generator::IceGridXmlGenerator generator;
298 generator.generateLocalApplication(scenario);
299 generator.generateRemoteApplication(scenario);
300
301 return 0;
302 }
303
304 localScen = scenario;
305
306 const char* n_argv[] = {argv[0], "--ArmarX.RedirectStdout=false"};
307 return armarx::Application::run(2, const_cast<char**>(n_argv));
308 }
309
310 std::string
311 ScenarioCli::packageChoosingDialog(std::string scenarioName)
312 {
313 using namespace ScenarioManager;
314 using namespace Parser;
315 using namespace Data_Structure;
316 using namespace Exec;
317 StringList packages = PackageBuilder::FilterPackagesForScenario(scenarioName);
318
319 if (packages.size() == 0)
320 {
321 return "";
322 }
323 else if (packages.size() == 1)
324 {
325 return packages[0];
326 }
327 else if (packages.size() > 1)
328 {
329 size_t answer = -1;
330 while (answer > packages.size())
331 {
332 std::cout
333 << "Found multiple possible packages for this Scenario path, please select: "
334 << std::endl;
335 int number = 1;
336 for (auto package : packages)
337 {
338 std::cout << number << ") " << package << std::endl;
339 number++;
340 }
341 std::cout << "Please enter a number now: " << std::endl;
342
343 std::string answerString;
344 std::cin >> answerString;
345 try
346 {
347 answer = boost::lexical_cast<size_t>(answerString);
348 }
349 catch (...)
350 {
351 std::cout << "ERROR: Could not convert input to a number - please type in a "
352 "number between 1 and "
353 << packages.size() << std::endl
354 << std::endl;
355 continue;
356 }
357
358 if (answer > packages.size() || answer == 0)
359 {
360 answer = -1;
361 continue;
362 }
363 answer -= 1;
364 }
365 return packages[answer];
366 }
367
368 return "";
369 }
370
371 void
372 ScenarioCli::startScenario(std::string command,
374 bool printOnly,
375 IceGrid::AdminPrx iceAdmin,
376 const std::string& commandLineParameters)
377 {
378 using namespace ScenarioManager;
379 using namespace Exec;
380 StopStrategyFactory stopStrategyFactory;
381 Executor executor(
382 stopStrategyFactory.getStopStrategy(StopperFactory::getFactory()->getPidStopper()),
383 StarterFactory::getFactory()->getStarter());
384
385 std::future<void> result;
386
387 StatusManager manager;
388
389 //look if the app is startet or not and look for pids
390 for (auto app : *scenario->getApplications())
391 {
392 app->setStatus(executor.getApplicationStatus(app));
393 }
394
395
396 if (command == "status")
397 {
398 std::cout << "Status of " << scenario->getName() << " is: ";
399
400 if (scenario->getStatus() ==
402 {
404 }
405 else if (scenario->getStatus() ==
407 {
409 }
410 else if (scenario->getStatus() ==
412 {
414 }
415 else if (scenario->getStatus() ==
417 {
419 }
420 else
421 {
423 }
424
425 std::cout << std::endl;
426
427 for (auto app : *scenario->getApplications())
428 {
429 std::cout << "\t " << app->getName() << " : ";
431 {
433 }
434 else if (app->getStatus() ==
436 {
438 }
439 else if (app->getStatus() ==
441 {
443 }
444 else
445 {
447 }
448
449 std::cout << std::endl;
450 }
451 return;
452 }
453 else if (command == "periodic_status")
454 {
455 while (true)
456 {
457 std::cout << "Status of " << scenario->getName() << " is: ";
458
459 if (scenario->getStatus() == "Running")
460 {
461 coloredStdOut("Running", 92);
462 }
463 else if (scenario->getStatus() == "Stopped")
464 {
465 coloredStdOut("Stopped", 31);
466 }
467 else if (scenario->getStatus() == "Mixed")
468 {
469 coloredStdOut("Mixed", 93);
470 }
471 std::cout << std::endl;
472 for (auto app : *scenario->getApplications())
473 {
474 app->setStatus(executor.getApplicationStatus(app));
475 }
476 TimeUtil::SleepMS(1000);
477 }
478 }
479 else if (command == "start")
480 {
481 if (!printOnly)
482 {
483 std::cout << "Starting Scenario ";
484 }
485 result = executor.startScenario(scenario, printOnly, commandLineParameters);
486 }
487 else if (command == "stop")
488 {
489 std::cout << "Stopping Scenario ";
490 result = executor.stopScenario(scenario);
491 }
492 else if (command == "kill")
493 {
494 std::cout << "Killing Scenario ";
495 executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(
496 StopperFactory::getFactory()->getPidStopper(), 500),
497 scenario);
498
499 result = executor.stopScenario(scenario);
500 }
501 else if (command == "restart")
502 {
503 ARMARX_INFO << "Restarting Scenario";
504 executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(
505 StopperFactory::getFactory()->getPidStopper(), 500),
506 scenario);
507
508 result = executor.restartScenario(scenario, printOnly);
509 }
510
511 if (!printOnly)
512 {
513 std::cout << scenario->getName() << std::endl;
514 }
515
516 result.wait();
517 }
518
519 void
520 ScenarioCli::startApplication(std::string command,
522 bool printOnly,
523 IceGrid::AdminPrx iceAdmin,
524 const std::string& commandLineParameters)
525 {
526 using namespace ScenarioManager;
527 using namespace Exec;
528 StopStrategyFactory stopStrategyFactory;
529 Executor executor(
530 stopStrategyFactory.getStopStrategy(StopperFactory::getFactory()->getPidStopper()),
531 StarterFactory::getFactory()->getStarter());
532
533 std::future<void> result;
534
535 StatusManager manager;
536
537 //look for app pid
538 app->setStatus(executor.getApplicationStatus(app));
539
540 if (command == "status")
541 {
542 std::cout << "Status of " << app->getName() << "is: ";
544 {
546 }
547 else if (app->getStatus() ==
549 {
551 }
552 else if (app->getStatus() ==
554 {
556 }
557 else
558 {
560 }
561 std::cout << std::endl;
562 return;
563 }
564 else if (command == "start")
565 {
566 if (!printOnly)
567 {
568 std::cout << "Starting Application ";
569 }
570
571 result = executor.startApplication(app, printOnly, commandLineParameters);
572 }
573 else if (command == "stop")
574 {
575 std::cout << "Stopping Application ";
576 result = executor.stopApplication(app);
577 }
578 else if (command == "kill")
579 {
580 std::cout << "Killing Application ";
581 executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(
582 StopperFactory::getFactory()->getByNameStopper(), 0),
583 app->getScenario());
584 result = executor.stopApplication(app);
585 }
586 else if (command == "restart")
587 {
588 std::cout << "Restarting Application ";
589 executor.setStopStrategy(stopStrategyFactory.getStopAndKillStrategy(
590 StopperFactory::getFactory()->getByNameStopper(), 0),
591 app->getScenario());
592 result = executor.restartApplication(app, printOnly);
593 }
594
595 if (!printOnly)
596 {
597 std::cout << app->getName() << std::endl;
598 }
599 result.wait();
600 }
601
602 void
603 ScenarioCli::coloredStdOut(std::string message, int colorCode)
604 {
605 std::cout << "\033[" << colorCode << "m" << message << "\033[0m";
606 }
607} // namespace armarx
std::shared_ptr< ScenarioManager::Data_Structure::ApplicationInstance > ApplicationInstancePtr
Definition StopStrategy.h:7
void generateLocalApplication(Data_Structure::ScenarioPtr scenario)
void generateRemoteApplication(Data_Structure::ScenarioPtr scenario)
int run(int argc, char *argv[]) override
Ice::Application replacement for the main function.
std::vector< std::string > getArmarXPackageNames()
getDefaultPackageNames returns the value of the ArmarX.DefaultPackages property It splits the string ...
void setIceProperties(Ice::PropertiesPtr properties) override
Overrides PropertyUser::setIceProperties() which is called internally.
static Ice::PropertiesPtr create(const Ice::PropertiesPtr &iceProperties=nullptr)
void setup(const ManagedIceObjectRegistryInterfacePtr &registry, Ice::PropertiesPtr properties) override
Setup method to be implemented by user applications.
int exec(const ArmarXManagerPtr &armarXManager) override
Exec method is the main process of the application.
static std::string GetScenarioNameByCommandLineInput(CmdOptions string)
static void SleepMS(float milliseconds)
Definition TimeUtil.h:203
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
Parser * parser
Definition Parser.cpp:34
::IceInternal::Handle<::Ice::Properties > PropertiesPtr
std::shared_ptr< Scenario > ScenarioPtr
Definition Scenario.h:35
std::shared_ptr< Package > PackagePtr
Definition Package.h:122
std::shared_ptr< ApplicationInstance > ApplicationInstancePtr
std::vector< std::string > StringList
Ice::PropertiesPtr mergeProperties(Ice::PropertiesPtr properties, int argc, char *argv[])
Merge command line options into properties.
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< ArmarXManager > ArmarXManagerPtr
IceUtil::Handle< ManagedIceObjectRegistryInterface > ManagedIceObjectRegistryInterfacePtr
Definition Application.h:83