Skip to content

Commit 6c84da1

Browse files
Use CLI11 for command line interfaces
Drop own command line parsing implementation.
1 parent b55776e commit 6c84da1

47 files changed

Lines changed: 784 additions & 1389 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

g2o/EXTERNAL/CLI11/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
include(FetchContent)
2+
FetchContent_Declare(
3+
cli11_proj
4+
QUIET
5+
GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
6+
# v2.5.0
7+
GIT_TAG 4160d259d961cd393fd8d67590a8c7d210207348
8+
)
9+
10+
FetchContent_MakeAvailable(cli11_proj)

g2o/EXTERNAL/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
add_subdirectory(CLI11)
2+
13
if (G2O_HAVE_OPENGL)
24
add_subdirectory(freeglut)
35
endif()

g2o/apps/g2o_cli/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ endif(UNIX)
2222
add_executable(g2o_cli_application
2323
g2o.cpp)
2424

25-
target_link_libraries(g2o_cli_application g2o_cli_library)
25+
target_link_libraries(g2o_cli_application PUBLIC g2o_cli_library)
26+
target_link_libraries(g2o_cli_application PRIVATE CLI11::CLI11)
2627

2728
set_target_properties(g2o_cli_application PROPERTIES OUTPUT_NAME g2o)
2829

g2o/apps/g2o_cli/g2o.cpp

Lines changed: 96 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <string>
3434
#include <string_view>
3535

36+
#include "CLI/CLI.hpp"
3637
#include "dl_wrapper.h"
3738
#include "g2o/core/batch_stats.h"
3839
#include "g2o/core/estimate_propagator.h"
@@ -45,7 +46,6 @@
4546
#include "g2o/core/robust_kernel_factory.h"
4647
#include "g2o/core/sparse_optimizer.h"
4748
#include "g2o/core/sparse_optimizer_terminate_action.h"
48-
#include "g2o/stuff/command_args.h"
4949
#include "g2o/stuff/filesys_tools.h"
5050
#include "g2o/stuff/logger.h"
5151
#include "g2o/stuff/macros.h"
@@ -112,91 +112,34 @@ struct IncrementalEdgesCompare {
112112

113113
int main(int argc, char** argv) {
114114
OptimizableGraph::initMultiThreading();
115-
int maxIterations;
116-
bool verbose;
115+
int maxIterations = 5;
116+
bool verbose = false;
117117
std::string inputFilename;
118118
std::string outputfilename;
119119
std::string solverProperties;
120-
std::string strSolver;
120+
std::string strSolver = "gn_var";
121121
std::string loadLookup;
122-
bool initialGuess;
123-
bool initialGuessOdometry;
124-
bool marginalize;
125-
bool listTypes;
126-
bool listSolvers;
127-
bool listRobustKernels;
128-
bool incremental;
129-
int gaugeId;
122+
bool initialGuess = false;
123+
bool initialGuessOdometry = false;
124+
bool marginalize = false;
125+
bool listTypes = false;
126+
bool listSolvers = false;
127+
bool listRobustKernels = false;
128+
bool incremental = false;
129+
int gaugeId = -1;
130130
std::string robustKernel;
131-
bool computeMarginals;
132-
bool printSolverProperties;
133-
double huberWidth;
134-
double gain;
135-
int maxIterationsWithGain;
131+
bool computeMarginals = false;
132+
bool printSolverProperties = false;
133+
double huberWidth = -1.;
134+
double gain = 1e-6;
135+
int maxIterationsWithGain = std::numeric_limits<int>::max();
136136
// double lambdaInit;
137137
int updateGraphEachN = 10;
138138
std::string statsFile;
139139
std::string summaryFile;
140-
bool nonSequential;
140+
bool nonSequential = false;
141141
// command line parsing
142142
std::vector<int> gaugeList;
143-
g2o::CommandArgs arg;
144-
arg.param("i", maxIterations, 5,
145-
"perform n iterations, if negative consider the gain");
146-
arg.param("gain", gain, 1e-6, "the gain used to stop optimization");
147-
arg.param("ig", maxIterationsWithGain, std::numeric_limits<int>::max(),
148-
"Maximum number of iterations with gain enabled");
149-
arg.param("v", verbose, false, "verbose output of the optimization process");
150-
arg.param("guess", initialGuess, false,
151-
"initial guess based on spanning tree");
152-
arg.param("guessOdometry", initialGuessOdometry, false,
153-
"initial guess based on odometry");
154-
arg.param("inc", incremental, false, "run incremetally");
155-
arg.param("update", updateGraphEachN, 10, "updates after x odometry nodes");
156-
arg.param("marginalize", marginalize, false, "on or off");
157-
arg.param("printSolverProperties", printSolverProperties, false,
158-
"print the properties of the solver");
159-
arg.param("solverProperties", solverProperties, "",
160-
"set the internal properties of a solver,\n\te.g., "
161-
"initialLambda=0.0001,maxTrialsAfterFailure=2");
162-
arg.param("robustKernel", robustKernel, "", "use this robust error function");
163-
arg.param("robustKernelWidth", huberWidth, -1.,
164-
"width for the robust Kernel (only if robustKernel)");
165-
arg.param("computeMarginals", computeMarginals, false,
166-
"computes the marginal covariances of something. FOR TESTING ONLY");
167-
arg.param("gaugeId", gaugeId, -1, "force the gauge");
168-
arg.param("o", outputfilename, "", "output final version of the graph");
169-
arg.param("solver", strSolver, "gn_var",
170-
"specify which solver to use underneat\n\t {gn_var, lm_fix3_2, "
171-
"gn_fix6_3, lm_fix7_3}");
172-
#ifndef G2O_DISABLE_DYNAMIC_LOADING_OF_LIBRARIES
173-
std::string dummy;
174-
arg.param("solverlib", dummy, "",
175-
"specify a solver library which will be loaded");
176-
arg.param("typeslib", dummy, "",
177-
"specify a types library which will be loaded");
178-
#endif
179-
arg.param("stats", statsFile, "", "specify a file for the statistics");
180-
arg.param("listTypes", listTypes, false, "list the registered types");
181-
arg.param("listRobustKernels", listRobustKernels, false,
182-
"list the registered robust kernels");
183-
arg.param("listSolvers", listSolvers, false, "list the available solvers");
184-
arg.param("renameTypes", loadLookup, "",
185-
"create a lookup for loading types into other types,\n\t "
186-
"TAG_IN_FILE=INTERNAL_TAG_FOR_TYPE,TAG2=INTERNAL2\n\t e.g., "
187-
"VERTEX_CAM=VERTEX_SE3:EXPMAP");
188-
arg.param("gaugeList", gaugeList, std::vector<int>(),
189-
"set the list of gauges separated by commas without spaces \n "
190-
"e.g: 1,2,3,4,5 ");
191-
arg.param("summary", summaryFile, "",
192-
"append a summary of this optimization run to the summary file "
193-
"passed as argument");
194-
arg.paramLeftOver("graph-input", inputFilename, "",
195-
"graph file which will be processed", true);
196-
arg.param("nonSequential", nonSequential, false,
197-
"apply the robust kernel only on loop closures and not odometries");
198-
199-
arg.parseArgs(argc, argv);
200143

201144
#ifndef G2O_DISABLE_DYNAMIC_LOADING_OF_LIBRARIES
202145
// registering all the types from the libraries
@@ -209,6 +152,84 @@ int main(int argc, char** argv) {
209152
if (verbose) cout << "# linked version of g2o\n";
210153
#endif
211154

155+
const std::vector<std::string> available_solvers = []() {
156+
std::vector<std::string> solvers;
157+
solvers.reserve(
158+
OptimizationAlgorithmFactory::instance()->creatorList().size());
159+
for (const auto& creator :
160+
OptimizationAlgorithmFactory::instance()->creatorList()) {
161+
solvers.emplace_back(creator->property().name);
162+
}
163+
return solvers;
164+
}();
165+
166+
CLI::App app{"g2o's CLI"};
167+
argv = app.ensure_utf8(argv);
168+
169+
app.add_option("-i,--iterations", maxIterations,
170+
"perform n iterations, if negative consider the gain")
171+
->check(CLI::Range(-1, 100000))
172+
->capture_default_str();
173+
app.add_option("--gain", gain, "the gain used to stop optimization");
174+
app.add_option("--iterations_gain", maxIterationsWithGain,
175+
"Maximum number of iterations with gain enabled");
176+
app.add_flag("-v", verbose, "verbose output of the optimization process");
177+
app.add_flag("--guess", initialGuess, "initial guess based on spanning tree");
178+
app.add_flag("--guess_odometry", initialGuessOdometry,
179+
"initial guess based on odometry");
180+
app.add_flag("--inc", incremental, "run incrementally");
181+
app.add_option("--update", updateGraphEachN,
182+
"updates after x odometry nodes");
183+
app.add_flag("--marginalize", marginalize, "marginalize landmarks");
184+
app.add_flag("--print_solver_properties", printSolverProperties,
185+
"print the properties of the solver");
186+
app.add_option("--solver_properties", solverProperties,
187+
"set the internal properties of a solver, e.g., "
188+
"initialLambda=0.0001,maxTrialsAfterFailure=2");
189+
app.add_option("--robust_kernel", robustKernel,
190+
"use this robust error function");
191+
app.add_option("--robust_kernel_width", huberWidth,
192+
"width for the robust Kernel (only if robustKernel)");
193+
app.add_flag(
194+
"--compute_marginals", computeMarginals,
195+
"computes the marginal covariances of something. FOR TESTING ONLY");
196+
app.add_option("--gauge_id", gaugeId, "force the gauge");
197+
app.add_option("-o,--output", outputfilename,
198+
"output final version of the graph");
199+
app.add_option("--solver", strSolver,
200+
"specify which solver to use underneath")
201+
->check(CLI::IsMember(available_solvers));
202+
#ifndef G2O_DISABLE_DYNAMIC_LOADING_OF_LIBRARIES
203+
std::string dummy;
204+
app.add_option("--solverlib", dummy,
205+
"specify a solver library which will be loaded");
206+
app.add_option("--typeslib", dummy,
207+
"specify a types library which will be loaded");
208+
#endif
209+
app.add_option("--stats", statsFile, "specify a file for the statistics");
210+
app.add_flag("--list_types", listTypes, "list the registered types");
211+
app.add_flag("--list_robust_kernels", listRobustKernels,
212+
"list the registered robust kernels");
213+
app.add_flag("--list_solvers", listSolvers, "list the available solvers");
214+
app.add_option("--rename_types", loadLookup,
215+
"create a lookup for loading types into other types, "
216+
"TAG_IN_FILE=INTERNAL_TAG_FOR_TYPE,TAG2=INTERNAL2, e.g., "
217+
"VERTEX_CAM=VERTEX_SE3:EXPMAP");
218+
app.add_option("--gauge_list", gaugeList,
219+
"set the list of gauges separated by commas without spaces, "
220+
"e.g: 1 2 3 4 5");
221+
app.add_option(
222+
"--summary", summaryFile,
223+
"append a summary of this optimization run to the summary file "
224+
"passed as argument");
225+
app.add_flag(
226+
"--non_sequential", nonSequential,
227+
"apply the robust kernel only on loop closures and not odometries");
228+
app.add_option("input", inputFilename, "graph file which will be processed")
229+
->check(CLI::ExistingFile);
230+
231+
CLI11_PARSE(app, argc, argv);
232+
212233
OptimizationAlgorithmFactory* solverFactory =
213234
OptimizationAlgorithmFactory::instance();
214235
if (listSolvers) {
@@ -411,10 +432,6 @@ int main(int argc, char** argv) {
411432
"the binary g2o_incremental"
412433
<< '\n';
413434
int incIterations = maxIterations;
414-
if (!arg.parsedParam("i")) {
415-
cerr << "# Setting default number of iterations\n";
416-
incIterations = 1;
417-
}
418435
int maxDim = 0;
419436

420437
cerr << "# incremental settings\n";

g2o/apps/g2o_cli/g2o_common.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ void loadStandardTypes(DlWrapper& dlTypesWrapper, int argc, char** argv) {
120120
}
121121

122122
std::vector<std::string> libs;
123-
if (argc > 0 && argv != nullptr) findArguments("-typeslib", libs, argc, argv);
123+
if (argc > 0 && argv != nullptr)
124+
findArguments("--typeslib", libs, argc, argv);
124125
for (const auto& lib : libs) {
125126
G2O_INFO("Loading types {}", lib);
126127
dlTypesWrapper.openLibrary(lib);
@@ -156,7 +157,7 @@ void loadStandardSolver(DlWrapper& dlSolverWrapper, int argc, char** argv) {
156157

157158
std::vector<std::string> libs;
158159
if (argc > 0 && argv != nullptr)
159-
findArguments("-solverlib", libs, argc, argv);
160+
findArguments("--solverlib", libs, argc, argv);
160161
for (const auto& lib : libs) {
161162
G2O_INFO("Loading solver {}", lib);
162163
dlSolverWrapper.openLibrary(lib);

g2o/apps/g2o_simulator/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
add_executable(g2o_simulator2d_application
22
g2o_simulator2d.cpp
33
)
4-
target_link_libraries(g2o_simulator2d_application simulator_lib types_slam2d_addons types_slam2d core)
4+
target_link_libraries(g2o_simulator2d_application PRIVATE simulator_lib types_slam2d_addons types_slam2d core)
5+
target_link_libraries(g2o_simulator2d_application PRIVATE CLI11::CLI11)
56
set_target_properties(g2o_simulator2d_application PROPERTIES OUTPUT_NAME g2o_simulator2d)
67

78
add_executable(g2o_simulator3d_application
89
g2o_simulator3d.cpp
910
)
10-
target_link_libraries(g2o_simulator3d_application simulator_lib types_slam3d_addons types_slam3d types_slam2d_addons types_slam2d core)
11+
target_link_libraries(g2o_simulator3d_application PRIVATE simulator_lib types_slam3d_addons types_slam3d types_slam2d_addons types_slam2d core)
12+
target_link_libraries(g2o_simulator3d_application PRIVATE CLI11::CLI11)
1113
set_target_properties(g2o_simulator3d_application PROPERTIES OUTPUT_NAME g2o_simulator3d)
1214

1315
install(TARGETS g2o_simulator2d_application g2o_simulator3d_application

g2o/apps/g2o_simulator/g2o_simulator2d.cpp

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,58 +28,77 @@
2828
#include <fstream>
2929
#include <iostream>
3030

31+
#include "CLI/CLI.hpp"
3132
#include "g2o/core/optimizable_graph.h"
3233
#include "g2o/simulator/simulator.h"
3334
#include "g2o/simulator/simulator2d_base.h"
34-
#include "g2o/stuff/command_args.h"
3535
#include "g2o/stuff/logger.h"
3636

3737
int main(int argc, char** argv) {
38-
g2o::CommandArgs arg;
3938
g2o::Simulator2D::Config simulator_config;
39+
// Setting up default
40+
simulator_config.nlandmarks = 100;
41+
simulator_config.nSegments = 1000;
42+
simulator_config.segmentGridSize = 50;
43+
simulator_config.minSegmentLength = 0.5;
44+
simulator_config.maxSegmentLength = 3;
45+
simulator_config.simSteps = 100;
46+
simulator_config.worldSize = 25.0;
4047

41-
G2O_INFO("Running 2D simulator");
48+
CLI::App app{"g2o Simulator 2D"};
49+
argv = app.ensure_utf8(argv);
4250

4351
std::string outputFilename;
44-
arg.param("nlandmarks", simulator_config.nlandmarks, 100,
45-
"number of landmarks in the map");
46-
arg.param("nSegments", simulator_config.nSegments, 1000,
47-
"number of segments");
48-
arg.param("segmentGridSize", simulator_config.segmentGridSize, 50,
49-
"number of cells of the grid where to align the segments");
50-
arg.param("minSegmentLength", simulator_config.minSegmentLength, 0.5,
51-
"minimal Length of a segment in the world");
52-
arg.param("maxSegmentLength", simulator_config.maxSegmentLength, 3,
53-
"maximal Length of a segment in the world");
52+
app.add_option("--num_landmarks", simulator_config.nlandmarks,
53+
"number of landmarks in the map")
54+
->check(CLI::NonNegativeNumber);
55+
app.add_option("--num_segments", simulator_config.nSegments,
56+
"number of segments")
57+
->check(CLI::NonNegativeNumber);
58+
app.add_option("--segment_grid_size", simulator_config.segmentGridSize,
59+
"number of cells of the grid where to align the segments")
60+
->check(CLI::PositiveNumber);
61+
app.add_option("--min_segment_length", simulator_config.minSegmentLength,
62+
"minimal Length of a segment in the world")
63+
->check(CLI::NonNegativeNumber);
64+
app.add_option("--max_segment_length", simulator_config.maxSegmentLength,
65+
"maximal Length of a segment in the world")
66+
->check(CLI::NonNegativeNumber);
5467

55-
arg.param("simSteps", simulator_config.simSteps, 100,
56-
"number of simulation steps");
57-
arg.param("worldSize", simulator_config.worldSize, 25.0, "size of the world");
58-
arg.param("hasOdom", simulator_config.hasOdom, false,
59-
"the robot has an odometry");
60-
arg.param("hasPointSensor", simulator_config.hasPointSensor, false,
61-
"the robot has a point sensor");
62-
arg.param("hasPointBearingSensor", simulator_config.hasPointBearingSensor,
63-
false, "the robot has a point bearing sensor");
64-
arg.param("hasPoseSensor", simulator_config.hasPoseSensor, false,
65-
"the robot has a pose sensor");
66-
arg.param("hasCompass", simulator_config.hasCompass, false,
67-
"the robot has a compass");
68-
arg.param("hasGPS", simulator_config.hasGPS, false, "the robot has a GPS");
69-
arg.param("hasSegmentSensor", simulator_config.hasSegmentSensor, false,
70-
"the robot has a segment sensor");
71-
arg.paramLeftOver("graph-output", outputFilename, "",
72-
"graph file which will be written", true);
68+
app.add_option("--sim_steps", simulator_config.simSteps,
69+
"number of simulation steps")
70+
->check(CLI::PositiveNumber);
71+
app.add_option("--world_size", simulator_config.worldSize,
72+
"size of the world")
73+
->check(CLI::PositiveNumber);
74+
app.add_flag("--has_odom", simulator_config.hasOdom,
75+
"the robot has an odometry");
76+
app.add_flag("--has_point_sensor", simulator_config.hasPointSensor,
77+
"the robot has a point sensor");
78+
app.add_flag("--has_point_bearing_sensor",
79+
simulator_config.hasPointBearingSensor,
80+
"the robot has a point bearing sensor");
81+
app.add_flag("--has_pose_sensor", simulator_config.hasPoseSensor,
82+
"the robot has a pose sensor");
83+
app.add_flag("--has_compass", simulator_config.hasCompass,
84+
"the robot has a compass");
85+
app.add_flag("--has_gps", simulator_config.hasGPS, "the robot has a GPS");
86+
app.add_flag("--has_segment_sensor", simulator_config.hasSegmentSensor,
87+
"the robot has a segment sensor");
88+
app.add_option("graph-output", outputFilename,
89+
"graph file which will be written ('-' for stdout)")
90+
->required();
7391

74-
arg.parseArgs(argc, argv);
92+
CLI11_PARSE(app, argc, argv);
7593

94+
G2O_INFO("Running 2D simulator");
7695
g2o::Simulator2D simulator(std::move(simulator_config));
7796
G2O_INFO("Setting up");
7897
simulator.setup();
7998
G2O_INFO("Simulate");
8099
simulator.simulate();
81100

82-
if (outputFilename.empty()) {
101+
if (outputFilename == "-") {
83102
G2O_INFO("Saving to stdout");
84103
simulator.world().graph().save(std::cout);
85104
} else {

0 commit comments

Comments
 (0)