178 lines
5.3 KiB
C++
178 lines
5.3 KiB
C++
/*********************************************************************
|
|
*
|
|
* Helper dùng chung cho test của gói: dựng goal/order giả và chờ trạng thái.
|
|
*
|
|
*********************************************************************/
|
|
#ifndef MISSION_ADAPTERS_TEST_MISSION_TEST_UTILS_H_
|
|
#define MISSION_ADAPTERS_TEST_MISSION_TEST_UTILS_H_
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
#include <mission_adapters/mission_adapters.h>
|
|
|
|
namespace mission_test
|
|
{
|
|
|
|
/**
|
|
* @brief NavigationClient giả: ghi lại mọi lệnh xuống navigation để test kiểm thứ tự và số lần.
|
|
*
|
|
* Không mô phỏng chuyển động — test tự quyết định khi nào outcome quay về.
|
|
*/
|
|
class FakeNavigationClient : public mission_adapters::NavigationClient
|
|
{
|
|
public:
|
|
bool dispatch(const std::shared_ptr<const mission_adapters::Mission>& mission) override
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
dispatched_.push_back(mission);
|
|
return accept_dispatch_;
|
|
}
|
|
|
|
void cancelActive(mission_adapters::MissionId id) override
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
cancelled_.push_back(id);
|
|
}
|
|
|
|
/// Ép navigation từ chối mọi mission tiếp theo.
|
|
void setAcceptDispatch(bool accept)
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
accept_dispatch_ = accept;
|
|
}
|
|
|
|
std::vector<std::shared_ptr<const mission_adapters::Mission>> dispatched() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
return dispatched_;
|
|
}
|
|
|
|
std::vector<mission_adapters::MissionId> cancelled() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
return cancelled_;
|
|
}
|
|
|
|
size_t dispatchCount() const
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
return dispatched_.size();
|
|
}
|
|
|
|
private:
|
|
mutable std::mutex mutex_;
|
|
std::vector<std::shared_ptr<const mission_adapters::Mission>> dispatched_;
|
|
std::vector<mission_adapters::MissionId> cancelled_;
|
|
bool accept_dispatch_ = true;
|
|
};
|
|
|
|
|
|
/// @brief Goal hợp lệ: quaternion đã chuẩn hoá (w=1) để qua được validate() của adapter.
|
|
inline robot_geometry_msgs::PoseStamped makeGoal(double x, double y)
|
|
{
|
|
robot_geometry_msgs::PoseStamped goal;
|
|
goal.header.frame_id = "map";
|
|
goal.pose.position.x = x;
|
|
goal.pose.position.y = y;
|
|
goal.pose.orientation.w = 1.0;
|
|
return goal;
|
|
}
|
|
|
|
/// @brief Mission dựng thẳng, không qua adapter — dùng cho test của MissionManager/Executor.
|
|
inline std::shared_ptr<mission_adapters::Mission> makeMission(double x, double y)
|
|
{
|
|
auto mission = std::make_shared<mission_adapters::Mission>();
|
|
mission->type = mission_adapters::MissionType::SIMPLE_GOAL;
|
|
mission->goal = makeGoal(x, y);
|
|
return mission;
|
|
}
|
|
|
|
/// @brief n mission độc lập, goal khác nhau.
|
|
inline std::vector<std::shared_ptr<mission_adapters::Mission>> makeMissions(int count)
|
|
{
|
|
std::vector<std::shared_ptr<mission_adapters::Mission>> missions;
|
|
missions.reserve(static_cast<size_t>(count));
|
|
for (int i = 0; i < count; ++i)
|
|
missions.push_back(makeMission(i, i));
|
|
|
|
return missions;
|
|
}
|
|
|
|
inline robot_protocol_msgs::Action makeAction(const std::string& id)
|
|
{
|
|
robot_protocol_msgs::Action action;
|
|
action.actionId = id;
|
|
action.actionType = "TEST";
|
|
return action;
|
|
}
|
|
|
|
/// @brief Node đã released (base). Order thật của fleet manager luôn có ít nhất phần base.
|
|
inline robot_protocol_msgs::Node makeNode(int sequence_id, bool add_action = false)
|
|
{
|
|
robot_protocol_msgs::Node node;
|
|
node.sequenceId = sequence_id;
|
|
node.nodeId = "node_" + std::to_string(sequence_id);
|
|
node.released = true;
|
|
node.nodePosition.x = sequence_id;
|
|
node.nodePosition.y = sequence_id;
|
|
|
|
if (add_action)
|
|
node.actions.push_back(makeAction("node_action_" + std::to_string(sequence_id)));
|
|
|
|
return node;
|
|
}
|
|
|
|
inline robot_protocol_msgs::Edge makeEdge(int sequence_id, bool add_action = false)
|
|
{
|
|
robot_protocol_msgs::Edge edge;
|
|
edge.sequenceId = sequence_id;
|
|
edge.edgeId = "edge_" + std::to_string(sequence_id);
|
|
edge.released = true;
|
|
|
|
if (add_action)
|
|
edge.actions.push_back(makeAction("edge_action_" + std::to_string(sequence_id)));
|
|
|
|
return edge;
|
|
}
|
|
|
|
inline robot_protocol_msgs::Order makeOrder(int node_count, const std::string& order_id = "order_1",
|
|
std::uint32_t order_update_id = 0)
|
|
{
|
|
robot_protocol_msgs::Order order;
|
|
order.orderId = order_id;
|
|
order.orderUpdateId = order_update_id;
|
|
|
|
for (int i = 0; i < node_count; ++i)
|
|
order.nodes.push_back(makeNode(i));
|
|
|
|
for (int i = 0; i < node_count - 1; ++i)
|
|
order.edges.push_back(makeEdge(i));
|
|
|
|
return order;
|
|
}
|
|
|
|
inline bool waitForState(mission_adapters::MissionManager& manager,
|
|
mission_adapters::MissionState expected,
|
|
std::chrono::milliseconds timeout)
|
|
{
|
|
const auto deadline = std::chrono::steady_clock::now() + timeout;
|
|
while (std::chrono::steady_clock::now() < deadline)
|
|
{
|
|
if (manager.state() == expected)
|
|
return true;
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
|
}
|
|
|
|
return manager.state() == expected;
|
|
}
|
|
|
|
} // namespace mission_test
|
|
|
|
#endif // MISSION_ADAPTERS_TEST_MISSION_TEST_UTILS_H_
|