参考高博视觉十四讲的做法
调用的顺序
1.将参数传入类型BundleParams中进行构造函数
BundleParams params(argc,argv);
2.构造函数中,会将所有的参数传入到类型CommandArgs中
BundleParams::BundleParams(int argc, char** argv)
{
arg.param("input", input, "", "file which will be processed");
arg.param("trust_region_strategy", trust_region_strategy, "levenberg_marquardt",
"Options are: levenberg_marquardt, dogleg.");
arg.param("linear_solver", linear_solver, "dense_schur", // iterative schur and cgnr(pcg) leave behind...
"Options are: sparse_schur, dense_schur, sparse_normal_cholesky");
arg.param("sparse_linear_algebra_library", sparse_linear_algebra_library, "suite_sparse", "Options are: suite_sparse and cx_sparse.");
arg.param("dense_linear_algebra_library", dense_linear_algebra_library, "eigen", "Options are: eigen and lapack.");
arg.param("ordering",ordering,"automatic","Options are: automatic, user.");
arg.param("robustify", robustify, false, "Use a robust loss function");
arg.param("num_threads",num_threads,1, "Number of threads.");
arg.param("num_iterations", num_iterations,10, "Number of iterations.");
arg.param("rotation_sigma", rotation_sigma, 0.0, "Standard deviation of camera rotation "
"perturbation.");
arg.param("translation_sigma", translation_sigma,0.0, "translation perturbation.");
arg.param("point_sigma",point_sigma,0.0,"Standard deviation of the point "
"perturbation.");
arg.param("random_seed", random_seed, 38401,"Random seed used to set the state ");
arg.param("initial_ply", initial_ply,"initial.ply","Export the BAL file data as a PLY file.");
arg.param("final_ply", final_ply, "final.ply", "Export the refined BAL file data as a PLY");
arg.parseArgs(argc, argv);//类型中的参数全部加入到std::vector<CommandArgument> _args中
}
3.arg.parseArgs解析这个parser的函数
3.1 小技巧,解析出-后面的参数
string name = "-hello";
string::size_type epos = name.find_first_not_of('-');
name = name.substr(epos); //hello
bool CommandArgs::parseArgs(int argc, char** argv, bool exitOnError)
{
_progName = argv[0]; //去掉第一个参数
int i;
for (i = 1; i < argc; i++) {
string name = argv[i];
if (name[0] != '-') { // each param has to start with at least one dash
//cerr << "Error: expecting parameter, got " << name << endl;
//printHelp(cerr);
//if (exitOnError)
//exit(1);
//return false;
break;
}
/* first check whether it's -- and we should not continue parsing */
//表示省略
if (name == "--") {
++i;
break;
}
string::size_type dashPos = name.find_first_not_of('-');
if (dashPos != string::npos)
name = name.substr(dashPos);
if (name == "help" || name == "h") {
printHelp(cout);
exit(0);
}
else {
// command line argument parsing
std::vector<CommandArgument>::iterator it = _args.begin();
for ( ; it != _args.end(); ++it) {
if (it->name == name) {
if (it->type == CAT_BOOL) {
if (!it->parsed) {
bool* data = static_cast<bool*>(it->data);
*data = !(*data);
}
it->parsed = true;
} else {
if(i >= argc-1) {
cerr << "Argument " << name << "needs value.\n";
printHelp(cerr);
if (exitOnError)
exit(1);
return false;
}
i++;
str2arg(argv[i], *it);
it->parsed = true;
}
break;
}
}
if (it == _args.end()) {
cerr << "Error: Unknown Option '" << name << "' (use -help to get list of options).\n";
if (exitOnError)
exit(1);
return false;
}
}
} // for argv[i]
if ((int)_leftOvers.size() > argc - i) {
cerr << "Error: program requires parameters" << endl;
printHelp(cerr);
if (exitOnError)
exit(1);
return false;
}
for (size_t j = 0; (i < argc && j < _leftOvers.size()); i++, j++) {
string* s = static_cast<string*>(_leftOvers[j].data);
*s = argv[i];
}
// the optional leftOvers
for (size_t j = 0; (i < argc && j < _leftOversOptional.size()); i++, j++) {
string* s = static_cast<string*>(_leftOversOptional[j].data);
*s = argv[i];
}
return true;
}
标准的代表输入参数的类
struct CommandArgument
{
std::string name;
std::string description;
int type;
void* data;
bool parsed;
bool optional;
CommandArgument() : name(""), description(""), type(0), data(0), parsed(false), optional(false)
{}
};
维护每个参数代表的具体的含义,使用一个枚举类
1,先定义出枚举类,每个值都是代表数字
enum CommandArgumentType
{
CAT_DOUBLE,
CAT_FLOAT,
CAT_INT,
CAT_STRING,
CAT_BOOL,
CAT_VECTOR_INT,
CAT_VECTOR_DOUBLE
};
2,使用枚举类和字符串关联起来
const char* CommandArgs::type2str(int t) const
{
switch (t) {
case CAT_DOUBLE:
return "<double>";
case CAT_FLOAT:
return "<float>";
case CAT_INT:
return "<int>";
case CAT_STRING:
return "<string>";
case CAT_BOOL:
return "<bool>";
case CAT_VECTOR_INT:
return "<vector_int>";
case CAT_VECTOR_DOUBLE:
return "<vector_double>";
}
return "";
}
调用解析的时候的例子
std::vector<CommandArgument> _args; //第一步把所有的参数给到参数列表中
void CommandArgs::param(const std::string& name, std::string& p, const std::string& defValue, const std::string& desc)
{
CommandArgument ca;
ca.name = name; //参数的名称
ca.description = desc; //参数的描述
ca.type = CAT_STRING; //参数的类型
ca.data = static_cast<void*>(&p); //参数的具体数据,不知道指向什么数据,用一个void指针
ca.parsed = false; //还没有解析出来
p = defValue; //把内容传给p这个变量
_args.push_back(ca);
}
C++的vector是可以加入空的内容的,例如
keypoint_2_landmark_id.push_back({});