参考资料: https://github.com/stulp/dmpbbo
前提:你已经阅读了黑盒子优化和动态运动原语的教程。
在将BBO应用于策略改进时(例如优化机器人上的DMP),“rollout”的概念变得很重要。rollout是使用一组策略参数(例如DMP的参数)执行策略(例如DMP)的结果。虽然优化的搜索空间是在策略参数的空间中,但成本是由rollout决定的。
从实现的角度来看,将BBO应用于策略改进(可能会执行dmp)需要几个扩展:
1.并行运行多个优化,针对DMP的每个自由度运行一个优化
2.使用任务的rolllouts/任务求解器来代替成本函数
Optimizing DMP DOFs in parallel(多自由度并行优化)
考虑一个7自由度的机械臂。在DMP中,每个DOF将由7-D DMP的不同维数表示(假设DMP的每个维数使用10个基函数)。针对成本函数,有两种不同的优化DMP参数的方法:
1.考虑优化的搜索空间为70-D,即在一个搜索空间中考虑DMP的所有开放参数。为此,您可以使用runOptimizationTask(),还可以参阅demoOptimizationTask.cpp和demoOptimizationDmp.cpp中的演示。缺点是奖励加权平均将需要更多的样本来执行鲁棒更新,特别是对于协方差矩阵,它是70X70!
2.为这7个dof分别运行一个优化。因此,这里我们有7个10-D搜索空间(每个自由度有不同的分布和样本),但对所有优化使用相同的成本。这就是在PI2中提出的。该方法不能充分利用不同自由度之间的协方差,但在实际应用中效果良好。为此,您必须使用runOptimizationParallel(),请参阅demoOptimizationDmpParallel.cpp中的演示。主要区别在于,必须使用D分布(存储在std::vector中),而不是使用一个分布(均值和协方差),每个DOF对应一个分布。
CostFunction vs Task/TaskSolver
当cost函数有一个简单的结构时,例如cost =
,很方便在cost function::evaluate()中实现函数
。
然而,在机器人技术中,区分任务(例如举起一个物体)和解决这个任务的实体(例如你的机器人,我的机器人,一个模拟机器人等)是合适的。对于这些情况,成本函数被分解为任务和任务求解器,如下所示:
CostFunction::evaluate(samples,costs) {TaskSolver::performRollout(samples,cost_vars)Task::evaluateRollout(cost_vars,costs)
}
任务/任务求解器的作用是:
1.任务求解器:在机器人上执行rollout(基于策略空间中的示例),并将与计算成本相关的所有变量保存到一个文件(称为cost_var .txt)中。
2.任务:根据成本相关变量确定成本。
这里的想法是,任务求解器(TaskSolver)使用样本来进行rollout(如样品代表的政策执行)的参数和计算相关的变量确定成本(例如,它记录在机器人的末端执行器的力量,如果这是需要最小化)
这种方法的一些其他优点:
1.不同的机器人可以解决完全相同的任务执行相同的任务。
2.机器人不需要知道成本函数来执行发布(他们也不应该知道),中间的成本相关变量可以存储到文件中以便可视化等等。
3.执行rollout(在机器人上联机)和执行评估/更新/采样(在计算机上脱机)的过程可以分开,因为有一个单独的任务求解器::performRollouts函数。
Implementation
在使用任务/任务求解器方法时,优化过程如下:
int n_dim = 2; // Optimize 2D problem// This is the cost function to be optimized
CostFunction* cost_function = new CostFunctionQuadratic(VectorXd::Zero(n_dim));// This is the initial distribution
DistributionGaussian* distribution = new DistributionGaussian(VectorXd::Random(n_dim),MatrixXd::Identity(n_dim)) // This is the updater which will update the distribution
double eliteness = 10.0;
Updater* updater = new UpdaterMean(eliteness);// Some variables
MatrixXd samples;
VectorXd costs;for (int i_update=1; i_update<=n_updates; i_update++)
{// 1. Sample from distributionint n_samples_per_update = 10;distribution->generateSamples(n_samples_per_update, samples);for (int i_sample=0; i_sample<n_samples_per_update; i_sample++){// 2A. Perform the rollouttask_solver->performRollout(sample.row(i_sample),cost_vars);// 2B. Evaluate the rollouttask->evaluateRollout(cost_vars,costs);costs[i_sample] = cur_costs[0];}// 3. Update parametersupdater->updateDistribution(*distribution, samples, costs, *distribution);}
Cost components
evaluateRollout返回一个成本向量。这便于跟踪不同的成本组成部分。例如,考虑这样一个任务,其成本包括以最小的加速通过viapoint。在这种情况下,成本组成部分是:1)到viapoint的距离和2)加速度的总和。然后
cost[1] = distance to the viapoint
cost[2] = acceleration
cost[0] = cost[1] + cost[2] (cost[0] must always be the sum of the individual cost components)
Cost-relevant variables
cost_vars应该包含与计算成本相关的所有变量。这完全取决于手头的任务。不管cost_vars包含什么,都应该确保任务和它的任务求解器是兼容的,并且对cost_vars中包含的内容有相同的理解。提示:对于机器人的发布,我通常让cost_vars中的每一行都是一个时间步骤中的相关变量。TaskViapoint给出了一个例子,它实现了一个任务,在这个任务中,cost_vars的前N列应该表示一个N- d轨迹。TaskSolverDmp遵守这个约定,它能够生成这样的轨迹。