一、简介
在使用SDK操作机器人时,常常需要用到位姿变换等功能。本文重点讲述这些功能的使用方法。
二、操作流程
1、SDK里运动学算法基于三方库PoseAlgebraBase,需要该库的动态链接库。在进行编译的时候,需要加上编译选项:-DELITE_COMPILE_POSE_ALG_PLUGIN=ON
2、在build\pose_alg_plugin文件夹下,会编译出该库的so和DLL。在使用时,需要到例如build\pose_alg_plugin\EigenPoseAlgebra\Release 里复制对应的DLL或者so到exe目录下
3、通过实例化PoseAlgebraBase,调用multiply、subtract等接口进行位姿变换。
三、常见问题
1、Q:为什么会有俩个DLL库?分别是EigenPoseAlgebra和ElitePoseAlgebra?
A:EigenPoseAlgebra基于Eigen 库,依赖 Eigen3,而ElitePoseAlgebra无额外依赖,手动展开循环,逐元素计算。在使用时,更推荐使用EigenPoseAlgebra,性能更好
四、代码和附件
// SPDX-License-Identifier: MIT
// Copyright (c) 2025, Elite Robots.
#include <Elite/ClassLoader.hpp>
#include <Elite/Log.hpp>
#include <Elite/PoseAlgebraBase.hpp>
#include <boost/program_options.hpp>
#include <iomanip>
#include <iostream>
#include <string>
using namespace ELITE;
namespace po = boost::program_options;
namespace {
void printVector6d(const std::string& name, const vector6d_t& value) {
std::cout << name << " = [";
for (size_t i = 0; i < value.size(); ++i) {
std::cout << std::fixed << std::setprecision(6) << value[i];
if (i + 1 < value.size()) {
std::cout << ", ";
}
}
std::cout << "]\n";
}
void printPoseMatrix(const std::string& name, const PoseMatrix& value) {
std::cout << name << " =\n";
for (size_t i = 0; i < 4; ++i) {
std::cout << " [";
for (size_t j = 0; j < 4; ++j) {
std::cout << std::fixed << std::setprecision(6) << value.data[i][j];
if (j + 1 < 4) {
std::cout << ", ";
}
}
std::cout << "]\n";
}
}
bool checkResult(const std::string& operation, bool ok, const PoseAlgebraResult& result) {
if (!ok) {
ELITE_LOG_ERROR("%s failed. error=%d, message=%s", operation.c_str(), static_cast<int>(result.error),
result.message.c_str());
return false;
}
return true;
}
} // namespace
int main(int argc, const char** argv) {
#if defined(ELITE_COMPILE_POSE_ALG_PLUGIN)
std::string plugin_lib_path;
std::string plugin_class = "ELITE::EigenPoseAlgebra";
po::options_description desc(
"Usage:\n"
"\t./pose_algebra_example <--plugin-lib=path> [--plugin-class=class_name]\n"
"Parameters:");
desc.add_options()("help,h", "Print help message")(
"plugin-lib", po::value<std::string>(&plugin_lib_path)->required(),
"\tRequired. Path to pose algebra plugin library.")(
"plugin-class", po::value<std::string>(&plugin_class)->default_value("ELITE::EigenPoseAlgebra"),
"\tOptional. Plugin class name.");
po::variables_map vm;
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
if (vm.count("help")) {
std::cout << desc << std::endl;
return 0;
}
po::notify(vm);
} catch (const po::error& e) {
std::cerr << "Argument error: " << e.what() << "\n\n";
std::cerr << desc << "\n";
return 1;
}
ClassLoader loader(plugin_lib_path);
if (!loader.loadLib()) {
ELITE_LOG_FATAL("Failed to load pose algebra plugin library: %s", plugin_lib_path.c_str());
return 1;
}
auto pose_algebra = loader.createUniqueInstance<PoseAlgebraBase>(plugin_class);
if (pose_algebra == nullptr) {
ELITE_LOG_FATAL("Failed to create PoseAlgebraBase instance: %s", plugin_class.c_str());
return 1;
}
const vector6d_t base_pose{0.400000, -0.200000, 0.500000, 0.100000, 0.200000, -0.300000};
const vector6d_t tool_offset{0.050000, 0.000000, 0.120000, 0.000000, 0.000000, 1.570796};
PoseAlgebraResult result;
PoseMatrix base_matrix;
if (!checkResult("vectorToMatrix(base_pose)", pose_algebra->vectorToMatrix(base_pose, base_matrix, result), result)) {
return 1;
}
PoseMatrix tool_matrix;
if (!checkResult("vectorToMatrix(tool_offset)", pose_algebra->vectorToMatrix(tool_offset, tool_matrix, result), result)) {
return 1;
}
PoseMatrix composed_matrix;
if (!checkResult("multiply(base_matrix, tool_matrix)",
pose_algebra->multiply(base_matrix, tool_matrix, composed_matrix, result), result)) {
return 1;
}
PoseMatrix tool_in_base_matrix;
if (!checkResult("worldToLocal(base_matrix, composed_matrix)",
pose_algebra->worldToLocal(base_matrix, composed_matrix, tool_in_base_matrix, result), result)) {
return 1;
}
PoseMatrix recovered_world_matrix;
if (!checkResult("localToWorld(base_matrix, tool_in_base_matrix)",
pose_algebra->localToWorld(base_matrix, tool_in_base_matrix, recovered_world_matrix, result),
result)) {
return 1;
}
PoseMatrix inverse_base_matrix;
if (!checkResult("inverse(base_matrix)", pose_algebra->inverse(base_matrix, inverse_base_matrix, result), result)) {
return 1;
}
PoseMatrix identity_check;
if (!checkResult("multiply(base_matrix, inverse_base_matrix)",
pose_algebra->multiply(base_matrix, inverse_base_matrix, identity_check, result), result)) {
return 1;
}
vector6d_t composed_pose;
if (!checkResult("matrixToVector(composed_matrix)",
pose_algebra->matrixToVector(composed_matrix, composed_pose, result), result)) {
return 1;
}
vector6d_t tool_in_base_pose;
if (!checkResult("worldToLocal(base_pose, composed_pose)",
pose_algebra->worldToLocal(base_pose, composed_pose, tool_in_base_pose, result), result)) {
return 1;
}
vector6d_t recovered_world_pose;
if (!checkResult("localToWorld(base_pose, tool_in_base_pose)",
pose_algebra->localToWorld(base_pose, tool_in_base_pose, recovered_world_pose, result), result)) {
return 1;
}
vector6d_t added_pose;
if (!checkResult("add(base_pose, tool_offset)", pose_algebra->add(base_pose, tool_offset, added_pose, result), result)) {
return 1;
}
vector6d_t recovered_pose;
if (!checkResult("subtract(added_pose, tool_offset)",
pose_algebra->subtract(added_pose, tool_offset, recovered_pose, result), result)) {
return 1;
}
PoseDistance dist_pose;
if (!checkResult("distance(base_pose, composed_pose)",
pose_algebra->distance(base_pose, composed_pose, dist_pose, result), result)) {
return 1;
}
std::cout << "=== Pose Algebra Example (Eigen Plugin) ===\n";
printVector6d("base_pose", base_pose);
printVector6d("tool_offset", tool_offset);
printPoseMatrix("base_matrix", base_matrix);
printPoseMatrix("composed_matrix", composed_matrix);
printPoseMatrix("tool_in_base_matrix", tool_in_base_matrix);
printPoseMatrix("recovered_world_matrix", recovered_world_matrix);
printPoseMatrix("identity_check", identity_check);
printVector6d("composed_pose", composed_pose);
printVector6d("tool_in_base_pose", tool_in_base_pose);
printVector6d("recovered_world_pose", recovered_world_pose);
printVector6d("added_pose", added_pose);
printVector6d("recovered_pose", recovered_pose);
std::cout << "distance.linear_distance = " << std::fixed << std::setprecision(6) << dist_pose.linear_distance
<< "\n";
std::cout << "distance.angular_distance = " << std::fixed << std::setprecision(6) << dist_pose.angular_distance
<< "\n";
return 0;
#else
std::cout << "pose_algebra_example: ELITE_COMPILE_POSE_ALG_PLUGIN is OFF, plugin demo is skipped.\n";
std::cout << "Reconfigure with: cmake -DELITE_COMPILE_POSE_ALG_PLUGIN=TRUE ..\n";
return 0;
#endif
}