您能否通过将 Pydrake 代码转换为 C++ 版本来演示一个关于符号变量和 Jacobian 的非常简单的 C++ 示例?
Could you demo a very simple C++ example about Symbolic variable and Jacobian by converting Pydrake code to C++ version?
我正在尝试将以下 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()
既然你用了名字“cost”,我想你想在 drake 的 MathematicalProgram 中使用它作为成本,所以我创建了 MyCost
class 可以在 Drake 的 MathematicalProgram 中使用。如果您以后不想使用 MathematicalProgram,您可以只使用模板化函数 DoEvalGeneric
而无需 class 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;
}
然后你可以在 cost_stage
的 return 参数上调用 Jacobian
。
我正在尝试将以下 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()
既然你用了名字“cost”,我想你想在 drake 的 MathematicalProgram 中使用它作为成本,所以我创建了 MyCost
class 可以在 Drake 的 MathematicalProgram 中使用。如果您以后不想使用 MathematicalProgram,您可以只使用模板化函数 DoEvalGeneric
而无需 class 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;
}
然后你可以在 cost_stage
的 return 参数上调用 Jacobian
。