微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

您能否通过将 Pydrake 代码转换为 C++ 版本来演示一个关于符号变量和雅可比行列式的非常简单的 C++ 示例?

如何解决您能否通过将 Pydrake 代码转换为 C++ 版本来演示一个关于符号变量和雅可比行列式的非常简单的 C++ 示例?

我正在尝试将以下 pydrake 代码转换为 C++ 版本。不幸的是,我迷失在非常严格的 C++ API 文档中。你能帮忙把下面的代码转换成 C++ 版本的教程吗?非常感谢!

import pydrake.math as drake_math
import pydrake.symbolic as sym

def cost_stage(x):
    m = sym if x.dtype == object else np # Check type for autodiff
    cost = m.sqrt(x[0]**2 + x[1]**2 ) 
    return cost

x_sym = np.array([sym.Variable("x_{}".format(i)) for i in range(n_x)])
x = x_sym
l = cost_stage(x)
self.l_x = sym.Jacobian([l],x).ravel()

解决方法

由于您使用了名称“成本”,我想您想将其用作 drake 的 MathematicalProgram 中的成本,因此我创建了可在 Drake 的 MathematicalProgram 中使用的 MyCost 类。如果您以后不想使用 MathematicalProgram,您可以只使用模板函数 DoEvalGeneric,而无需使用类 MyCost

这是 C++ 伪代码(我没有编译或运行代码,所以代码中很可能存在错误,但你懂的)

#include "drake/solvers/cost.h"
#include "drake/common/symbolic.h"

class MyCost : public drake::solvers::Cost {
 public:
  MyCost() {}
 
 protected:
  void DoEval(const Eigen::Ref<const Eigen::VectorXd>& x,Eigen::VectorXd* y) const override {
    DoEvalGeneric<double>(x,y);
  }

  void DoEval(const Eigen::Ref<const drake::AutoDiffVecXd>& x,drake::AutoDiffVecXd* y) const override {
    DoEvalGeneric<drake::AutoDiffXd>(x,y)
  }
  
  void DoEval(const Eigen::Ref<const drake::VectorX<drake::symbolic::Variable>>& x,drake::VectorX<drake::symbolic::Expression>* y) const override {
    DoEvalGeneric<drake::symbolic::Expression>(x.cast<drake::symbolic::Expression>(),y);
  }

 private:
  template <typename T>
  void DoEvalGeneric(const Eigen::Ref<const drake::VectorX<T>>& x,drake::VectorX<T>* y) const {
    y->resize(1);
    using std::sqrt
    (*y)(0) = sqrt(x[0] * x[0] + x[1] * x[1]);
  }
};

void main() {
  const drake::symbolic::Variable x0{"x0"};
  const drake::symbolic::Variable x1{"x1"};
  drake::Vector2<drake::symbolic::Variable> x(x0,x1);
  MyCost cost{};
  drake::VectorX<drake::symbolic::Expression> y;
  cost.Eval(x,&y);
  std::cout << y(0).Jacobian(x) << "\n";
}

这里我创建了一个模板化函数 DoEvalGeneirc 来处理三种不同的标量类型 double、AutoDiffXd 和符号表达式。您可以在 drake 代码库中看到类似的模式 https://github.com/RobotLocomotion/drake/blob/6ee5e9325821277a62bd5cd5456ccf02ca25dab7/solvers/cost.cc#L14-L33

如果您不需要在 drake MathematicalProgram 中使用 cost,那么您可以在 C++ 中将 cost 函数创建为

#include "drake/common/symbolic.h"

#include <Eigen/Core>


template <typename Derived>
typename Derived::Scalar cost_stage(const Derived& x) {
  using std::sqrt;
  return sqrt(x[0] * x[0] + x[1] * x[1]);
}

int main() {
  const drake::symbolic::Variable x0{"x0"};
  const drake::symbolic::Variable x1{"x1"};
  drake::Vector2<drake::symbolic::Variable> x(x0,x1);
  const drake::symbolic::Expression l = cost_stage(x.cast<drake::symbolic::Expression>());
  std::cout << l.Jacobian(x) << "\n";
  return 0;
}

然后您可以对 Jacobian 的返回参数调用 cost_stage

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。