6.6 KiB
Viết một nguồn mission mới
Nguồn mission là plugin duy nhất của gói này. Thêm một loại nguồn (REST, fleet manager riêng,
teach-pendant, file kịch bản...) không cần sửa dòng nào trong src/.
Việc thực thi action không thuộc đây: adapter chỉ chuyển dữ liệu, navigation runtime mới là nơi chạy action.
1. Chọn tên schema
Schema là chuỗi định danh loại payload, và là thứ core dùng để định tuyến. Đặt tên theo miền dữ liệu, không theo tên hãng hay giao thức truyền tải:
vda5050.order # đã có
geometry.pose_stamped # đã có
json.pick_and_place # ví dụ nguồn mới
Hai adapter khai cùng một schema sẽ bị registry từ chối — định tuyến khi đó phụ thuộc thứ tự nạp, tức phụ thuộc vào thứ tự dòng trong file YAML.
2. Hiện thực MissionSourceAdapter
#include <boost/dll/alias.hpp>
#include <mission_adapters/adapter.h>
namespace mission_plugins
{
class PickAndPlaceAdapter : public mission_adapters::MissionSourceAdapter
{
public:
static mission_adapters::MissionSourceAdapter::Ptr create()
{
return std::make_shared<PickAndPlaceAdapter>();
}
bool configure(const std::string& name, robot::NodeHandle& nh) override
{
// Param riêng nằm trong namespace tên instance.
nh.getParam(name + "/global_frame", global_frame_, std::string("map"));
return !global_frame_.empty();
}
std::string schema() const override { return "json.pick_and_place"; }
bool validate(const mission_adapters::MissionRequest& request,
std::string& reason) const override
{
if (request.raw_payload.empty())
{
reason = "payload rỗng";
return false;
}
return true;
}
mission_adapters::ConversionResult
convert(const mission_adapters::MissionRequest& request) override
{
mission_adapters::ConversionResult result;
// ... parse request.raw_payload, dựng mission ...
return result;
}
private:
std::string global_frame_ = "map";
};
} // namespace mission_plugins
BOOST_DLL_ALIAS(mission_plugins::PickAndPlaceAdapter::create, PickAndPlaceAdapter)
Bốn quy tắc bắt buộc:
- State là member, không phải
staticlocal. Một tiến trình có thể chạy nhiều instance; state static sẽ nối chúng lại và order của robot này ảnh hưởng robot kia. validate()chặn dữ liệu hỏng trước khi nó tới navigation: NaN/Inf, quaternion không chuẩn hoá được, payload thiếu trường. Trảfalsekèmreasoncụ thể — chuỗi đó đi thẳng vào log.convert()trả rỗng nghĩa là "không có việc", KHÔNG phải lỗi và KHÔNG phải lệnh huỷ. Core sẽ bỏ qua và giữ nguyên hàng đợi đang chạy. Đây là bất biến A1: một order lỗi từ fleet manager không được âm thầm xoá order đang chạy.- Mission
has_goal == falsephải có ít nhất một action. Mission không goal và cũng không action là chặng không có việc gì để làm, và nó sẽ không bao giờ báo kết quả về — mission layer kẹtRUNNINGvĩnh viễn. Core kiểm lại điều này và bỏ cả lô nếu phát hiện.
SubmitMode — thay hay nối tiếp
ConversionResult::mode quyết định mission mới quan hệ thế nào với hàng đợi đang có:
| mode | Ý nghĩa | Dùng khi |
|---|---|---|
kReplace (mặc định) |
Thay toàn bộ hàng đợi, chặng đang chạy bị preempt và được bảo dừng | Yêu cầu mới, độc lập với việc đang làm |
kAppend |
Chỉ thêm vào cuối hàng đợi, không đụng chặng đang chạy | Phần nối tiếp của chính yêu cầu đang chạy |
kAppend là hình dạng của VDA5050 order update. Trả kReplace cho một bản cập nhật nghĩa là mỗi
lần fleet manager release thêm horizon, robot lại huỷ và chạy lại chặng đang đi.
3. Build thành .so riêng
add_library(mission_adapters_pick_and_place SHARED plugins/pick_and_place_adapter.cpp)
target_compile_options(mission_adapters_pick_and_place PRIVATE -Wall -Wextra)
set_target_properties(mission_adapters_pick_and_place PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(mission_adapters_pick_and_place
PUBLIC mission_adapters
PRIVATE Boost::boost Threads::Threads
)
install(TARGETS mission_adapters_pick_and_place
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
)
Thêm dependency cho plugin thì phải cập nhật đủ bốn chỗ: CMakeLists.txt, package.xml,
install rule, và file YAML.
4. Khai báo trong YAML — đừng quên library_path
Trong pnkx_nav_core/config/mission_adapters_params.yaml:
mission_adapters:
mission_sources:
- {name: pick_src, type: PickAndPlaceAdapter} # type = tên symbol trong BOOST_DLL_ALIAS
pick_src:
global_frame: map # param riêng của instance, đọc trong configure()
PickAndPlaceAdapter:
library_path: libmission_adapters_pick_and_place # BẮT BUỘC
Ba tên phải khớp nhau:
| Nơi | Giá trị |
|---|---|
BOOST_DLL_ALIAS(..., PickAndPlaceAdapter) |
tên symbol |
mission_sources[].type |
cùng tên symbol |
<type>/library_path |
tên file .so (không cần đuôi) |
Thiếu library_path là lỗi phổ biến nhất: plugin build sạch, .so nằm đúng chỗ, nhưng runtime
báo "không tìm thấy". Registry sẽ nêu đích danh khoá bị thiếu trong log.
Tên không có đuôi .so được resolve qua PNKX_NAV_CORE_LIBRARY_PATH, devel/lib, rồi
LD_LIBRARY_PATH — nên phải source devel/setup.bash trước khi chạy, nếu không plugin sẽ không
được tìm thấy dù file có thật.
5. Kiểm chứng
catkin_make --pkg mission_adapters
source devel/setup.bash
PNKX_NAV_CORE_CONFIG_DIR=src/AMR_T800/Test/mission_adapters/test/config \
./devel/lib/mission_adapters/plugin_registry_test
Nên có test cho: payload hợp lệ, payload thiếu trường, payload chứa NaN/Inf, payload không sinh mission nào, và (nếu nguồn có state) hai yêu cầu liên tiếp.
6. Nguồn không cần .so
Nguồn biên dịch thẳng vào host thì bỏ qua bước 3 và 4, đăng ký trực tiếp:
registry.registerAdapter(std::make_shared<PickAndPlaceAdapter>());
Đường này dùng trong test và cho host muốn kiểm soát vòng đời adapter; phần còn lại của luồng (validate, convert, định tuyến theo schema) giống hệt.