optimal & fix file cmake
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/dll/import.hpp>
|
||||
@@ -39,6 +40,17 @@ bool isFiniteTwist(const robot_geometry_msgs::Twist& twist)
|
||||
ControllerRunner::ControllerRunner() = default;
|
||||
ControllerRunner::~ControllerRunner() = default;
|
||||
|
||||
void ControllerRunner::attachStats(RuntimeStats* stats)
|
||||
{
|
||||
stats_ = stats;
|
||||
if (stats_ == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
section_compute_ = stats_->section("controller.compute");
|
||||
section_local_plan_ = stats_->section("controller.getLocalPlan");
|
||||
}
|
||||
|
||||
bool ControllerRunner::configure(const robot::NodeHandle& nh,
|
||||
const std::shared_ptr<tf3::BufferCore>& tf,
|
||||
robot_costmap_2d::Costmap2DROBOT* costmap, const PosePort* pose,
|
||||
@@ -46,13 +58,13 @@ bool ControllerRunner::configure(const robot::NodeHandle& nh,
|
||||
{
|
||||
if (configured_)
|
||||
{
|
||||
error = "ControllerRunner::configure() gọi lần thứ hai";
|
||||
error = "ControllerRunner::configure() called twice";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (costmap == nullptr)
|
||||
{
|
||||
error = "ControllerRunner cần costmap local khác null";
|
||||
error = "ControllerRunner needs a non-null local costmap";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -60,7 +72,7 @@ bool ControllerRunner::configure(const robot::NodeHandle& nh,
|
||||
{
|
||||
// Gen-2 nhận pose làm THAM SỐ của computeVelocityCommands/isGoalReached; không có nguồn pose
|
||||
// thì không gọi được hàm nào trong hai hàm đó.
|
||||
error = "ControllerRunner cần PosePort khác null";
|
||||
error = "ControllerRunner needs a non-null PosePort";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -72,7 +84,7 @@ bool ControllerRunner::configure(const robot::NodeHandle& nh,
|
||||
|
||||
if (!initial_controller.empty() && !swapPlanner(initial_controller))
|
||||
{
|
||||
error = "không nạp được local planner khởi đầu '" + initial_controller + "'";
|
||||
error = "could not load the initial local planner '" + initial_controller + "'";
|
||||
configured_ = false;
|
||||
return false;
|
||||
}
|
||||
@@ -85,6 +97,35 @@ robot_nav_core2::LocalPlanner* ControllerRunner::acquire(const std::string& name
|
||||
const auto cached = controllers_.find(name);
|
||||
if (cached != controllers_.end())
|
||||
{
|
||||
if (!marker_dirty_)
|
||||
{
|
||||
return cached->second.instance.get();
|
||||
}
|
||||
|
||||
// Marker vừa đổi: instance này có thể đã đọc `maker_name` trong initialize() và không bao giờ
|
||||
// đọc lại. Dựng lại từ factory sẵn có (không dlopen lại); instance mới thay chỗ instance cũ
|
||||
// CHỈ khi initialize() thành công — thất bại thì giữ nguyên cache và trả lỗi để bên gọi từ
|
||||
// chối yêu cầu, không để lại trạng thái nửa vời.
|
||||
try
|
||||
{
|
||||
robot_nav_core2::LocalPlanner::Ptr fresh = cached->second.factory();
|
||||
if (!fresh)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: factory of '%s' returned nullptr while "
|
||||
"rebuilding for the new marker.\n", name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
fresh->initialize(nh_, name, tf_, costmap_);
|
||||
cached->second.instance = std::move(fresh);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: rebuilding '%s' for the new marker failed: "
|
||||
"%s\n",
|
||||
name.c_str(), ex.what());
|
||||
return nullptr;
|
||||
}
|
||||
marker_dirty_ = false;
|
||||
return cached->second.instance.get();
|
||||
}
|
||||
|
||||
@@ -93,8 +134,8 @@ robot_nav_core2::LocalPlanner* ControllerRunner::acquire(const std::string& name
|
||||
|
||||
if (library_path.empty())
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: không tìm được thư viện cho '%s' — kiểm khoá "
|
||||
"'%s/library_path' trong YAML và sự tồn tại của file .so trong devel/lib.\n",
|
||||
robot::log_error("[move_base2] ControllerRunner: no library found for '%s' — check the key "
|
||||
"'%s/library_path' in the YAML and that the .so file exists in devel/lib.\n",
|
||||
name.c_str(), name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
@@ -108,13 +149,13 @@ robot_nav_core2::LocalPlanner* ControllerRunner::acquire(const std::string& name
|
||||
}
|
||||
catch (const boost::system::system_error& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: không nạp được symbol '%s' từ '%s': %s\n",
|
||||
robot::log_error("[move_base2] ControllerRunner: could not load symbol '%s' from '%s': %s\n",
|
||||
name.c_str(), library_path.c_str(), ex.what());
|
||||
return nullptr;
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: lỗi khi nạp '%s': %s\n", name.c_str(),
|
||||
robot::log_error("[move_base2] ControllerRunner: error while loading '%s': %s\n", name.c_str(),
|
||||
ex.what());
|
||||
return nullptr;
|
||||
}
|
||||
@@ -125,14 +166,15 @@ robot_nav_core2::LocalPlanner* ControllerRunner::acquire(const std::string& name
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: factory của '%s' ném exception: %s\n",
|
||||
robot::log_error("[move_base2] ControllerRunner: factory of '%s' threw an exception: %s\n",
|
||||
name.c_str(), ex.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!loaded.instance)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: factory của '%s' trả nullptr.\n", name.c_str());
|
||||
robot::log_error("[move_base2] ControllerRunner: factory of '%s' returned nullptr.\n",
|
||||
name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -144,15 +186,59 @@ robot_nav_core2::LocalPlanner* ControllerRunner::acquire(const std::string& name
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: initialize() của '%s' ném exception: %s\n",
|
||||
robot::log_error("[move_base2] ControllerRunner: initialize() of '%s' threw an exception: %s\n",
|
||||
name.c_str(), ex.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto inserted = controllers_.emplace(name, std::move(loaded));
|
||||
// Instance mới vừa initialize() với `maker_name` hiện hành — marker không còn "chưa được đọc".
|
||||
marker_dirty_ = false;
|
||||
return inserted.first->second.instance.get();
|
||||
}
|
||||
|
||||
bool ControllerRunner::setDockingMarker(const std::string& marker)
|
||||
{
|
||||
if (!configured_)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: setDockingMarker() before configure().\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate với danh sách `maker_sources` (chuỗi cách nhau bằng space, maker_sources.yaml) —
|
||||
// đúng phép kiểm bản cũ làm ở cửa dockTo (move_base.cpp:1161-1173). Marker lạ phải bị chặn ở
|
||||
// đây: để lọt xuống thì getMaker() của docking planner âm thầm không match source nào và robot
|
||||
// đứng im không lý do.
|
||||
std::string sources;
|
||||
nh_.param("maker_sources", sources, std::string(""));
|
||||
std::stringstream ss(sources);
|
||||
std::string source;
|
||||
bool known = false;
|
||||
while (ss >> source)
|
||||
{
|
||||
if (source == marker)
|
||||
{
|
||||
known = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!known)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: marker '%s' is not listed in maker_sources "
|
||||
"('%s').\n", marker.c_str(), sources.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string current;
|
||||
nh_.param("maker_name", current, std::string(""));
|
||||
if (current != marker)
|
||||
{
|
||||
nh_.setParam("maker_name", marker);
|
||||
marker_dirty_ = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControllerRunner::applyPendingLimits(robot_nav_core2::LocalPlanner* controller)
|
||||
{
|
||||
if (controller == nullptr)
|
||||
@@ -180,7 +266,8 @@ void ControllerRunner::applyPendingLimits(robot_nav_core2::LocalPlanner* control
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: lỗi khi áp lại trần vận tốc: %s\n", ex.what());
|
||||
robot::log_error("[move_base2] ControllerRunner: error while re-applying the velocity limits: "
|
||||
"%s\n", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,19 +275,22 @@ bool ControllerRunner::swapPlanner(const std::string& planner_name)
|
||||
{
|
||||
if (!configured_)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: swapPlanner() trước configure().\n");
|
||||
robot::log_error("[move_base2] ControllerRunner: swapPlanner() before configure().\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (planner_name.empty())
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: tên controller rỗng.\n");
|
||||
robot::log_error("[move_base2] ControllerRunner: empty controller name.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (planner_name == active_name_ && active_ != nullptr)
|
||||
if (planner_name == active_name_ && active_ != nullptr && !marker_dirty_)
|
||||
{
|
||||
return true; // Đã đúng controller; không log để khỏi spam ở cửa vào mỗi yêu cầu.
|
||||
// Đã đúng controller; không log để khỏi spam ở cửa vào mỗi yêu cầu. Riêng khi marker vừa đổi
|
||||
// thì KHÔNG được đi tắt: dock lại cùng planner với marker khác phải rơi xuống acquire() để
|
||||
// instance được dựng lại và initialize() đọc `maker_name` mới.
|
||||
return true;
|
||||
}
|
||||
|
||||
robot_nav_core2::LocalPlanner* controller = acquire(planner_name);
|
||||
@@ -213,33 +303,21 @@ bool ControllerRunner::swapPlanner(const std::string& planner_name)
|
||||
active_ = controller;
|
||||
active_name_ = planner_name;
|
||||
has_active_goal_ = false; // Instance mới chưa biết goal nào.
|
||||
active_plan_.clear();
|
||||
applyPendingLimits(active_);
|
||||
|
||||
robot::log_info("[move_base2] ControllerRunner: local planner đang dùng là '%s'.\n",
|
||||
robot::log_info("[move_base2] ControllerRunner: active local planner is '%s'.\n",
|
||||
planner_name.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControllerRunner::setTolerance(double xy_m, double yaw_rad)
|
||||
{
|
||||
if (!configured_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Interface gen-1 không có hàm đặt sai số; bản cũ ghi vào param rồi để planner tự đọc lại. Kênh
|
||||
// gián tiếp này được giữ nguyên để không đổi hành vi của các planner đang chạy — nhưng planner
|
||||
// nào chỉ đọc param lúc initialize sẽ KHÔNG thấy giá trị mới. Xem doc của lớp.
|
||||
nh_.setParam("xy_goal_tolerance", xy_m);
|
||||
nh_.setParam("yaw_goal_tolerance", yaw_rad);
|
||||
}
|
||||
|
||||
bool ControllerRunner::setPlan(const std::vector<robot_geometry_msgs::PoseStamped>& plan)
|
||||
{
|
||||
if (!configured_ || active_ == nullptr)
|
||||
{
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: setPlan() khi chưa có controller.\n");
|
||||
"[move_base2] ControllerRunner: setPlan() with no controller "
|
||||
"loaded.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -247,7 +325,7 @@ bool ControllerRunner::setPlan(const std::vector<robot_geometry_msgs::PoseStampe
|
||||
{
|
||||
// Plan rỗng lọt xuống sẽ thành front()/back() trên vector rỗng bên trong planner.
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: từ chối plan rỗng.\n");
|
||||
"[move_base2] ControllerRunner: rejecting an empty plan.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -259,7 +337,8 @@ bool ControllerRunner::setPlan(const std::vector<robot_geometry_msgs::PoseStampe
|
||||
if (path.poses.empty())
|
||||
{
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: plan chuyển sang Path2D bị rỗng.\n");
|
||||
"[move_base2] ControllerRunner: plan converted to Path2D came out "
|
||||
"empty.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -269,17 +348,84 @@ bool ControllerRunner::setPlan(const std::vector<robot_geometry_msgs::PoseStampe
|
||||
active_->setGoalPose(goal_pose);
|
||||
active_->setPlan(path);
|
||||
has_active_goal_ = true;
|
||||
active_plan_ = plan;
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: '%s' ném exception trong setPlan: "
|
||||
"[move_base2] ControllerRunner: '%s' threw an exception in setPlan: "
|
||||
"%s\n", active_name_.c_str(), ex.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ControllerRunner::refreshActivePlanner()
|
||||
{
|
||||
if (!configured_ || active_ == nullptr)
|
||||
{
|
||||
// Chưa có controller active thì không có cache nào cần refresh. Hành vi này giúp footprint có
|
||||
// thể được host đặt trước goal đầu tiên mà không biến thành lỗi khởi tạo.
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto loaded = controllers_.find(active_name_);
|
||||
if (loaded == controllers_.end())
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: active local planner '%s' is absent from "
|
||||
"the plugin cache.\n", active_name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool had_active_goal = has_active_goal_;
|
||||
const std::vector<robot_geometry_msgs::PoseStamped> saved_plan = active_plan_;
|
||||
if (had_active_goal && saved_plan.empty())
|
||||
{
|
||||
// Không thay instance cũ nếu không thể khôi phục goal đang chạy. Giữ controller hiện tại vẫn
|
||||
// an toàn hơn việc âm thầm biến navigation thành controller không có plan.
|
||||
robot::log_error("[move_base2] ControllerRunner: active planner '%s' has a goal but no "
|
||||
"cached plan to restore after a footprint change.\n", active_name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
robot_nav_core2::LocalPlanner::Ptr fresh;
|
||||
try
|
||||
{
|
||||
fresh = loaded->second.factory();
|
||||
if (!fresh)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: factory of '%s' returned nullptr while "
|
||||
"refreshing its footprint cache.\n", active_name_.c_str());
|
||||
return false;
|
||||
}
|
||||
fresh->initialize(nh_, active_name_, tf_, costmap_);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
// Chỉ thay cache SAU initialize thành công, nên lỗi này không làm mất controller cũ.
|
||||
robot::log_error("[move_base2] ControllerRunner: refreshing '%s' after a footprint change "
|
||||
"failed: %s\n", active_name_.c_str(), ex.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
loaded->second.instance = std::move(fresh);
|
||||
active_ = loaded->second.instance.get();
|
||||
has_active_goal_ = false;
|
||||
active_plan_.clear();
|
||||
applyPendingLimits(active_);
|
||||
|
||||
if (had_active_goal && !setPlan(saved_plan))
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: could not restore the active plan after "
|
||||
"refreshing '%s' for a footprint change.\n", active_name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
robot::log_info("[move_base2] ControllerRunner: refreshed '%s' after the local costmap "
|
||||
"footprint changed.\n", active_name_.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ControllerRunner::currentPose(robot_nav_2d_msgs::Pose2DStamped& pose) const
|
||||
{
|
||||
if (pose_ == nullptr)
|
||||
@@ -302,8 +448,8 @@ bool ControllerRunner::computeVelocityCommands(robot_geometry_msgs::Twist& cmd)
|
||||
if (!configured_ || active_ == nullptr)
|
||||
{
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: computeVelocityCommands() khi chưa "
|
||||
"có controller.\n");
|
||||
"[move_base2] ControllerRunner: computeVelocityCommands() with no "
|
||||
"controller loaded.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -317,7 +463,8 @@ bool ControllerRunner::computeVelocityCommands(robot_geometry_msgs::Twist& cmd)
|
||||
if (!currentPose(pose))
|
||||
{
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: mất pose, không tính lệnh.\n");
|
||||
"[move_base2] ControllerRunner: pose lost, not computing a "
|
||||
"command.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -325,6 +472,9 @@ bool ControllerRunner::computeVelocityCommands(robot_geometry_msgs::Twist& cmd)
|
||||
|
||||
try
|
||||
{
|
||||
// Đo đúng lời gọi vào plugin, không đo cả hàm: phần còn lại (tra pose, kiểm NaN) là chi phí của
|
||||
// move_base2, còn đây mới là chi phí của local planner đang cấu hình.
|
||||
ScopedSection timer(stats_, section_compute_);
|
||||
// Gen-2 trả THẲNG lệnh (không có cờ thành công/thất bại) và ném exception khi không tính được —
|
||||
// ngược với gen-1. Vì vậy nhánh "không có lệnh hợp lệ" ở đây là nhánh catch.
|
||||
const robot_nav_2d_msgs::Twist2DStamped cmd_2d =
|
||||
@@ -334,7 +484,7 @@ bool ControllerRunner::computeVelocityCommands(robot_geometry_msgs::Twist& cmd)
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: '%s' không sinh được lệnh: %s\n",
|
||||
"[move_base2] ControllerRunner: '%s' produced no command: %s\n",
|
||||
active_name_.c_str(), ex.what());
|
||||
return false;
|
||||
}
|
||||
@@ -344,7 +494,8 @@ bool ControllerRunner::computeVelocityCommands(robot_geometry_msgs::Twist& cmd)
|
||||
// VelocityArbiter cũng chặn NaN/Inf, nhưng chặn ngay tại nguồn cho biết ĐÚNG plugin nào đang
|
||||
// trả dữ liệu hỏng — arbiter chỉ thấy một con số vô nghĩa không rõ từ đâu.
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: '%s' trả lệnh chứa NaN/Inf.\n",
|
||||
"[move_base2] ControllerRunner: '%s' returned a command containing "
|
||||
"NaN/Inf.\n",
|
||||
active_name_.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -378,6 +529,7 @@ bool ControllerRunner::isGoalReached()
|
||||
if (reached)
|
||||
{
|
||||
has_active_goal_ = false;
|
||||
active_plan_.clear();
|
||||
}
|
||||
return reached;
|
||||
}
|
||||
@@ -386,7 +538,7 @@ bool ControllerRunner::isGoalReached()
|
||||
// Trả false: "chưa tới đích" là phía an toàn — báo nhầm đã tới sẽ kết thúc chặng đường sớm và
|
||||
// robot dừng ở chỗ không phải đích.
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: '%s' ném exception trong "
|
||||
"[move_base2] ControllerRunner: '%s' threw an exception in "
|
||||
"isGoalReached: %s\n", active_name_.c_str(), ex.what());
|
||||
return false;
|
||||
}
|
||||
@@ -403,6 +555,7 @@ void ControllerRunner::getLocalPlan(robot_nav_2d_msgs::Path2D& plan)
|
||||
|
||||
try
|
||||
{
|
||||
ScopedSection timer(stats_, section_local_plan_);
|
||||
active_->getPlan(plan);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
@@ -410,8 +563,8 @@ void ControllerRunner::getLocalPlan(robot_nav_2d_msgs::Path2D& plan)
|
||||
// Không phải mọi planner đều hỗ trợ; gen-2 cho phép ném. Đây chỉ là dữ liệu hiển thị nên nuốt
|
||||
// exception là đúng — nhưng vẫn log để không ai tưởng rviz đang hiện quỹ đạo thật.
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: '%s' không trả được quỹ đạo cục bộ: "
|
||||
"%s\n", active_name_.c_str(), ex.what());
|
||||
"[move_base2] ControllerRunner: '%s' could not return a local "
|
||||
"trajectory: %s\n", active_name_.c_str(), ex.what());
|
||||
plan = robot_nav_2d_msgs::Path2D();
|
||||
}
|
||||
}
|
||||
@@ -423,7 +576,8 @@ void ControllerRunner::setMeasuredVelocity(const robot_geometry_msgs::Twist& vel
|
||||
// Giữ giá trị cũ thay vì đưa NaN vào hàm tính lệnh — nhiều local planner dùng nó làm mốc giới
|
||||
// hạn gia tốc, và NaN ở đó lan ra toàn bộ cost function.
|
||||
robot::log_error_throttle(kHotPathLogThrottle,
|
||||
"[move_base2] ControllerRunner: bỏ vận tốc đo được chứa NaN/Inf.\n");
|
||||
"[move_base2] ControllerRunner: dropping a measured velocity "
|
||||
"containing NaN/Inf.\n");
|
||||
return;
|
||||
}
|
||||
measured_velocity_ = velocity;
|
||||
@@ -433,7 +587,8 @@ bool ControllerRunner::setTwistLinear(const robot_geometry_msgs::Vector3& linear
|
||||
{
|
||||
if (!std::isfinite(linear.x) || !std::isfinite(linear.y) || !std::isfinite(linear.z))
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: trần vận tốc thẳng chứa NaN/Inf, bỏ qua.\n");
|
||||
robot::log_error("[move_base2] ControllerRunner: linear velocity limit contains NaN/Inf, "
|
||||
"ignored.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -463,7 +618,8 @@ bool ControllerRunner::setTwistLinear(const robot_geometry_msgs::Vector3& linear
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: '%s' ném exception trong setTwistLinear: %s\n",
|
||||
robot::log_error("[move_base2] ControllerRunner: '%s' threw an exception in setTwistLinear: "
|
||||
"%s\n",
|
||||
active_name_.c_str(), ex.what());
|
||||
return false;
|
||||
}
|
||||
@@ -473,7 +629,8 @@ bool ControllerRunner::setTwistAngular(const robot_geometry_msgs::Vector3& angul
|
||||
{
|
||||
if (!std::isfinite(angular.x) || !std::isfinite(angular.y) || !std::isfinite(angular.z))
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: trần vận tốc góc chứa NaN/Inf, bỏ qua.\n");
|
||||
robot::log_error("[move_base2] ControllerRunner: angular velocity limit contains NaN/Inf, "
|
||||
"ignored.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -491,7 +648,8 @@ bool ControllerRunner::setTwistAngular(const robot_geometry_msgs::Vector3& angul
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
robot::log_error("[move_base2] ControllerRunner: '%s' ném exception trong setTwistAngular: %s\n",
|
||||
robot::log_error("[move_base2] ControllerRunner: '%s' threw an exception in setTwistAngular: "
|
||||
"%s\n",
|
||||
active_name_.c_str(), ex.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user