添加注释
This commit is contained in:
parent
2e01a6035a
commit
b4468809da
@ -1,12 +1,12 @@
|
||||
src1100_agvs {
|
||||
id: "agv_src1100"
|
||||
ip: "192.168.192.5"
|
||||
port_status: 19301
|
||||
port_control: 19301
|
||||
port_nav: 19301
|
||||
port_config: 19301
|
||||
port_other: 19301
|
||||
port_push: 19301
|
||||
port_status: 19204
|
||||
port_control: 19205
|
||||
port_nav: 19206
|
||||
port_config: 19207
|
||||
port_other: 19210
|
||||
port_push: 19302
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,11 @@
|
||||
//
|
||||
// Created by linbo on 2025/6/20.
|
||||
//
|
||||
/**
|
||||
* @file agv_src1100.h
|
||||
* @brief 仙工智能 SRC-1100/2200 系列 AGV 控制器设备实现类的头文件。
|
||||
* 继承自 AbstractAgv,实现了所有纯虚接口,并管理多端口 TCP 连接。
|
||||
*/
|
||||
#ifndef AGV_SRC1100_H
|
||||
#define AGV_SRC1100_H
|
||||
#pragma once
|
||||
@ -10,78 +15,292 @@
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace cmvr::device {
|
||||
|
||||
class AgvSrc1100 final : public AbstractAgv {
|
||||
public:
|
||||
explicit AgvSrc1100(const XmlNode& cfg);
|
||||
explicit AgvSrc1100(const config::AGVsrc1100Config& cfg);
|
||||
~AgvSrc1100() override;
|
||||
/**
|
||||
* @brief 仙工智能 SRC-1100/2200 系列 AGV 控制器设备实现类
|
||||
*
|
||||
* 继承自 AbstractAgv,实现了与仙工智能 SRC 系列控制器通信的具体协议。
|
||||
* 支持多端口(状态、控制、导航、配置、推送)并发连接和指令交互。
|
||||
*
|
||||
* @note 该类不是线程安全的,外部调用需自行保证同一设备实例的串行访问。
|
||||
*/
|
||||
class AgvSrc1100 final : public AbstractAgv {
|
||||
public:
|
||||
// ==================== 构造 / 析构 ====================
|
||||
|
||||
Status state() const override;
|
||||
std::string lastError() const override;
|
||||
/**
|
||||
* @brief 从 XML 配置节点构造设备实例(已弃用或未使用,保留兼容)
|
||||
* @param cfg XML 配置节点,包含设备 ID、IP、端口、启用标志等
|
||||
*/
|
||||
explicit AgvSrc1100(const XmlNode& cfg);
|
||||
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void update() override;
|
||||
/**
|
||||
* @brief 从 Protobuf 配置对象构造设备实例
|
||||
* @param cfg AGVsrc1100Config 配置对象,包含设备 ID、IP、端口、启用标志等
|
||||
*/
|
||||
explicit AgvSrc1100(const config::AGVsrc1100Config& cfg);
|
||||
|
||||
void getStatusInfo(AgvStatusInfo& info) override;
|
||||
void getBatteryStatus(BatteryStatus& info, bool simple = false) override;
|
||||
void getRobotLocation(RobotLocation& info) override;
|
||||
void downloadMap(DownloadMapResult& info, const std::string& map_name) override;
|
||||
void getMapStatus(MapStatus& info) override;
|
||||
void uploadMap(UploadMapResult& info, const std::string& map_json) override;
|
||||
void lockRobotControl(LockResult& info, const std::string& nick_name) override;
|
||||
void getCurrentLockStatus(CurrentLockStatus& info) override;
|
||||
/**
|
||||
* @brief 析构函数,自动停止设备并释放资源
|
||||
*/
|
||||
~AgvSrc1100() override;
|
||||
|
||||
void robotMotionControl(MotionCtrlRes& res, const MotionCtrlReq& req) override;
|
||||
// ==================== 生命周期管理(通用) ====================
|
||||
|
||||
void robotLoadMap(LoadMapRes& res, const LoadMapReq& req) override;
|
||||
/**
|
||||
* @brief 获取当前设备运行状态
|
||||
* @return Status 枚举值(CREATED / INITIALIZED / RUNNING / PAUSED / STOPPED / FAULT)
|
||||
*/
|
||||
Status state() const override;
|
||||
|
||||
void queryLoadMapStatus(QueryLoadMapStatusRes& res) override;
|
||||
void queryStationList(QueryStationRes& res) override;
|
||||
/**
|
||||
* @brief 获取最后一次发生的错误信息
|
||||
* @return 错误描述字符串,若无错误则返回空字符串
|
||||
*/
|
||||
std::string lastError() const override;
|
||||
|
||||
void robotGoTargetList(GoTargetListRes& res, const GoTargetListReq& req) override;
|
||||
/**
|
||||
* @brief 启动设备,标记为运行状态
|
||||
* @note 所有 socket 连接应在构造时已完成,启动仅改变状态标志
|
||||
*/
|
||||
void start() override;
|
||||
|
||||
/**
|
||||
* @brief 停止设备,关闭所有 TCP 连接并释放资源
|
||||
*/
|
||||
void stop() override;
|
||||
|
||||
/**
|
||||
* @brief 周期性更新设备状态
|
||||
* @note 当前为空实现,可扩展心跳检测或重连逻辑
|
||||
*/
|
||||
void update() override;
|
||||
|
||||
// ==================== 端口 19204 – 机器人状态 API(允许 10 个连接) ====================
|
||||
// 功能:查询机器人各种状态信息(只读操作,不改变机器人状态)
|
||||
|
||||
/**
|
||||
* @brief 查询机器人基本信息(命令码 1000, robot_status_info_req)
|
||||
* @param info 输出参数,填充 AgvStatusInfo
|
||||
* @note 返回信息包括:版本、型号、地图名称、网络 IP、MAC、Wi-Fi 信号等
|
||||
*/
|
||||
void getStatusInfo(AgvStatusInfo& info) override;
|
||||
|
||||
/**
|
||||
* @brief 查询电池状态(命令码 1007, robot_status_battery_req)
|
||||
* @param info 输出参数,填充 BatteryStatus
|
||||
* @param simple 若为 true,仅返回关键电量信息(当前实现未区分)
|
||||
* @note 返回信息包括:电量百分比、温度、充放电状态、电压、电流等
|
||||
*/
|
||||
void getBatteryStatus(BatteryStatus& info, bool simple = false) override;
|
||||
|
||||
/**
|
||||
* @brief 查询机器人当前位置(命令码 1004, robot_status_loc_req)
|
||||
* @param info 输出参数,填充 RobotLocation
|
||||
* @note 返回信息包括:世界坐标系 X/Y 坐标、朝向角、定位置信度、当前站点
|
||||
*/
|
||||
void getRobotLocation(RobotLocation& info) override;
|
||||
|
||||
/**
|
||||
* @brief 查询地图状态(命令码 1300, robot_status_map_req)
|
||||
* @param info 输出参数,填充 MapStatus
|
||||
* @note 返回信息包括:当前载入的地图名称、所有存储的地图列表、文件详情
|
||||
*/
|
||||
void getMapStatus(MapStatus& info) override;
|
||||
|
||||
/**
|
||||
* @brief 查询当前控制权持有者(命令码 1060, robot_status_current_lock_req)
|
||||
* @param info 输出参数,填充 CurrentLockStatus
|
||||
* @note 返回信息包括:是否被锁定、持有者 IP/端口/昵称、锁定时间等
|
||||
*/
|
||||
void getCurrentLockStatus(CurrentLockStatus& info) override;
|
||||
|
||||
/**
|
||||
* @brief 查询地图载入状态(命令码 1022, robot_status_loadmap_req)
|
||||
* @param res 输出参数,包含 loadmap_status
|
||||
* @note loadmap_status: 0=失败, 1=成功, 2=载入中(载入中禁止重定位)
|
||||
*/
|
||||
void queryLoadMapStatus(QueryLoadMapStatusRes& res) override;
|
||||
|
||||
/**
|
||||
* @brief 查询当前地图站点列表(命令码 1301, robot_status_station_req)
|
||||
* @param res 输出参数,填充 QueryStationRes,包含所有站点信息
|
||||
* @note 返回信息包括:站点 ID、类型、坐标、朝向角、属性等
|
||||
*/
|
||||
void queryStationList(QueryStationRes& res) override;
|
||||
|
||||
/**
|
||||
* @brief 查询当前导航状态(命令码 1020, robot_status_task_req)
|
||||
* @param res 输出参数,填充 RobotStatusTaskCurrentRes
|
||||
* @param req 输入参数,simple=true 时只返回 task_status
|
||||
* @note 返回信息包括:任务状态、任务类型、目标站点/坐标、已走/未走路径
|
||||
*/
|
||||
void robotStatusTaskCurrent(RobotStatusTaskCurrentRes& res, const RobotStatusTaskCurrentReq& req) override;
|
||||
|
||||
/**
|
||||
* @brief 批量查询任务状态(命令码 1110, robot_status_task_status_package_req)
|
||||
* @param res 输出参数,填充 QueryTaskStatusPackageRes
|
||||
* @param req 输入参数,task_ids 列表;若为空则查询所有未完成 + 最近一条已完成的任务
|
||||
* @note 返回信息包括:任务列表、每个任务的 ID/状态/类型、进度百分比、剩余距离等
|
||||
*/
|
||||
void robotStatusTaskPackage(QueryTaskStatusPackageRes& res, const QueryTaskStatusPackageReq& req) override;
|
||||
|
||||
// ==================== 端口 19205 – 机器人控制 API(允许 5 个连接) ====================
|
||||
// 功能:下发控制指令,改变机器人运动或状态(非导航类指令)
|
||||
|
||||
/**
|
||||
* @brief 下发开环速度运动指令(命令码 2010, robot_control_motion_req)
|
||||
* @param res 输出参数,执行结果
|
||||
* @param req 输入参数,包含 vx/vy/w/steer/real_steer/duration
|
||||
* @warning 下发此指令会立即取消当前正在执行的导航任务
|
||||
* @note 多舵轮设备仅 vx/vy/w 生效,steer/real_steer 仅单舵轮设备有效
|
||||
*/
|
||||
void robotMotionControl(MotionCtrlRes& res, const MotionCtrlReq& req) override;
|
||||
|
||||
/**
|
||||
* @brief 切换载入地图(命令码 2022, robot_control_loadmap_req)
|
||||
* @param res 输出参数,执行结果
|
||||
* @param req 输入参数,目标地图名称
|
||||
* @note 目标地图必须已存在于机器人中,否则切换失败
|
||||
*/
|
||||
void robotLoadMap(LoadMapRes& res, const LoadMapReq& req) override;
|
||||
|
||||
// ==================== 端口 19206 – 机器人导航 API(允许 5 个连接) ====================
|
||||
// 功能:下发导航任务
|
||||
|
||||
/**
|
||||
* @brief 指定路径导航(命令码 3066, robot_task_gotargetlist_req)
|
||||
* @param res 输出参数,下发结果(ret_code=0 仅表示指令被接收,不表示执行完成)
|
||||
* @param req 输入参数,包含 move_task_list(站点序列)
|
||||
* @attention
|
||||
* - 每个任务必须含 task_id、source_id、id 三个必填字段
|
||||
* - source_id 和 id 之间必须有直接相连的线路,不可跳点
|
||||
* - 任务会排队执行,前一个任务失败时后续任务自动取消
|
||||
* - 适合多车调度场景
|
||||
*/
|
||||
void robotGoTargetList(GoTargetListRes& res, const GoTargetListReq& req) override;
|
||||
|
||||
/**
|
||||
* @brief 单点站点自动规划导航(命令码 3051, robot_task_gotarget_req)
|
||||
* @param res 输出参数,下发结果(ret_code=0 仅表示指令被接收)
|
||||
* @param req 输入参数,支持自由导航(freeGo)和基于站点的路径导航两种模式
|
||||
* @warning
|
||||
* - **严禁用于多车调度场景**,仅限单车测试/任务链验证
|
||||
* - 下发新任务会取消当前正在执行的任务(不排队)
|
||||
* - 成功下发后会自动清除指定的 warning/error 报错码
|
||||
* - 自由导航(freeGo)仅支持双轮差速底盘
|
||||
*/
|
||||
void robotGoTarget(RobotGoTargetRes& res, const RobotGoTargetReq& req) override;
|
||||
|
||||
// ==================== 端口 19207 – 机器人配置 API(允许 5 个连接) ====================
|
||||
// 功能:配置类操作(地图上传/下载、控制权管理、参数修改等)
|
||||
|
||||
/**
|
||||
* @brief 抢占机器人控制权(命令码 4005, robot_config_lock_req)
|
||||
* @param info 输出参数,填充 LockResult
|
||||
* @param nick_name 抢占者昵称,用于标识调用方
|
||||
* @note 抢占成功后调用方获得独占控制权,其他方仅可查询状态
|
||||
*/
|
||||
void lockRobotControl(LockResult& info, const std::string& nick_name) override;
|
||||
|
||||
/**
|
||||
* @brief 上传地图(命令码 4010, robot_config_uploadmap_req)
|
||||
* @param info 输出参数,填充 UploadMapResult
|
||||
* @param map_json 地图 JSON 字符串(完整的地图文件内容)
|
||||
* @note 地图数据较大时会自动分片发送,需确保 JSON 格式正确
|
||||
*/
|
||||
void uploadMap(UploadMapResult& info, const std::string& map_json) override;
|
||||
|
||||
/**
|
||||
* @brief 下载指定地图(命令码 4011, robot_config_downloadmap_req)
|
||||
* @param info 输出参数,填充 DownloadMapResult(包含地图 JSON 内容)
|
||||
* @param map_name 要下载的地图名称
|
||||
* @note 下载的地图内容以 JSON 字符串形式存储在 info.map_content 中
|
||||
*/
|
||||
void downloadMap(DownloadMapResult& info, const std::string& map_name) override;
|
||||
|
||||
// ==================== 端口 19210 – 其他 API(允许 5 个连接) ====================
|
||||
// 功能:外设控制(顶升/货叉/辊筒/音频/IO 等)
|
||||
// 当前未实现具体方法,预留扩展
|
||||
|
||||
// ==================== 端口 19301 – 机器人推送 API(允许 10 个连接) ====================
|
||||
// 功能:接收机器人主动推送的实时状态数据
|
||||
// 相关配置方法(如 9300)可能在此,当前未实现
|
||||
|
||||
|
||||
void robotStatusTask(RobotStatusTaskRes& res, const RobotStatusTaskReq& req) override;
|
||||
// ---------- 新增任务控制接口(3001/3002/3003)及停止运动(2000) ----------
|
||||
void robotTaskPause(RobotTaskPauseRes& res) override;
|
||||
void robotTaskResume(RobotTaskResumeRes& res) override;
|
||||
void robotTaskCancel(RobotTaskCancelRes& res) override;
|
||||
void robotControlStop(RobotControlStopRes& res) override;
|
||||
|
||||
|
||||
private:
|
||||
// ==================== 私有通信辅助函数 ====================
|
||||
|
||||
/**
|
||||
* @brief 异步连接指定端口
|
||||
* @param sock 输出参数,连接成功后存储 socket 文件描述符
|
||||
* @param port 目标端口号(19204/19205/19206/19207/19210/19301)
|
||||
* @note 在独立线程中执行,连接成功后将 sock 设置为有效值
|
||||
*/
|
||||
void asyncConnect(int& sock, int port);
|
||||
|
||||
/**
|
||||
* @brief 发送请求并接收完整响应
|
||||
* @param sock 已连接的 socket 文件描述符
|
||||
* @param header 16 字节协议帧头
|
||||
* @return true 表示收发成功,current_json_ 中存储响应 JSON;false 表示失败
|
||||
* @note 内部先发送帧头,然后循环接收直到超时,最后提取 JSON 部分
|
||||
*/
|
||||
bool sendAndRecv(int sock, const uint8_t* header);
|
||||
|
||||
/**
|
||||
* @brief 清空 socket 接收缓冲区中的残留数据
|
||||
* @param sock 目标 socket 文件描述符
|
||||
* @note 采用非阻塞方式读取并丢弃所有可读数据,防止粘包干扰
|
||||
*/
|
||||
void flushSocket(int sock);
|
||||
|
||||
/**
|
||||
* @brief 设置 socket 接收超时时间
|
||||
* @param sock 目标 socket 文件描述符
|
||||
* @param timeout_ms 超时时间(毫秒),0 表示取消超时
|
||||
*/
|
||||
void setSocketTimeout(int sock, int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief 解析 JSON 字符串并做异常捕获
|
||||
* @param json_str 输入的 JSON 字符串
|
||||
* @param root 输出参数,解析后的 json 对象
|
||||
* @param err_msg 输出参数,解析失败时的错误信息
|
||||
* @return true 表示解析成功,false 表示解析失败
|
||||
*/
|
||||
bool parseJson(const std::string& json_str, json& root, std::string& err_msg);
|
||||
|
||||
|
||||
// ==================== 成员变量 ====================
|
||||
|
||||
mutable std::mutex mutex_; ///< 保护状态和错误信息的互斥锁
|
||||
std::atomic<Status> status_{Status::CREATED}; ///< 当前设备运行状态(原子变量)
|
||||
std::string last_error_; ///< 最后一次错误信息
|
||||
std::string current_json_; ///< 最近一次响应的 JSON 内容(由 sendAndRecv 填充)
|
||||
|
||||
// ---------- 各端口 Socket 文件描述符 ----------
|
||||
int sock_status_ = -1; ///< 19204 – 状态 API 端口
|
||||
int sock_control_ = -1; ///< 19205 – 控制 API 端口
|
||||
int sock_nav_ = -1; ///< 19206 – 导航 API 端口
|
||||
int sock_config_ = -1; ///< 19207 – 配置 API 端口
|
||||
int sock_other_ = -1; ///< 19210 – 其他 API 端口
|
||||
int sock_push_ = -1; ///< 19301 – 推送 API 端口
|
||||
|
||||
private:
|
||||
void asyncConnect(int& sock, int port);
|
||||
bool sendAndRecv(int sock, const uint8_t* header);
|
||||
void flushSocket(int sock);
|
||||
void setSocketTimeout(int sock, int timeout_ms);
|
||||
|
||||
|
||||
|
||||
// 辅助函数:将JSON字符串解析为Json::Value,同时做错误处理
|
||||
bool parseJson(const std::string& json_str, json& root, std::string& err_msg);
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
std::atomic<Status> status_{Status::CREATED};
|
||||
std::string last_error_;
|
||||
std::string current_json_;
|
||||
|
||||
|
||||
|
||||
// 多socket
|
||||
int sock_status_ = -1;
|
||||
int sock_control_ = -1;
|
||||
int sock_nav_ = -1;
|
||||
int sock_config_ = -1;
|
||||
int sock_other_ = -1;
|
||||
int sock_push_ = -1;
|
||||
|
||||
std::vector<std::thread> connect_threads_;
|
||||
mutable std::mutex connect_mutex_;
|
||||
};
|
||||
std::vector<std::thread> connect_threads_; ///< 各端口异步连接线程
|
||||
mutable std::mutex connect_mutex_; ///< 保护 connect_threads_ 的互斥锁
|
||||
};
|
||||
|
||||
} // namespace cmvr::device
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,14 @@
|
||||
//
|
||||
// Created by xtkuang on 2025/6/1.
|
||||
//
|
||||
/**
|
||||
* @file grpc_agv_service.h
|
||||
* @brief gRPC AGV 服务实现类的头文件。
|
||||
* 继承自自动生成的 api::AgvService::Service,提供所有 AGV 相关 RPC 接口的具体实现。
|
||||
* 通过 DeviceManager 获取对应的 AGV 设备实例(如 AgvSrc1100),将请求转发至设备层。
|
||||
* @author xtkuang
|
||||
* @date 2025-06-01
|
||||
*/
|
||||
|
||||
#ifndef GRPC_AGV_SERVICE_H
|
||||
#define GRPC_AGV_SERVICE_H
|
||||
@ -11,121 +19,260 @@
|
||||
|
||||
namespace cmvr::service {
|
||||
|
||||
class gRPCAGVServiceImpl final : public api::AgvService::Service {
|
||||
public:
|
||||
gRPCAGVServiceImpl();
|
||||
~gRPCAGVServiceImpl() override = default;
|
||||
/**
|
||||
* @brief gRPC AGV 服务实现类。
|
||||
* 负责将 gRPC 请求转换为对具体 AGV 设备的调用,并统一处理异常、日志和时间戳。
|
||||
*/
|
||||
class gRPCAGVServiceImpl final : public api::AgvService::Service {
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数,获取 DeviceManager 单例引用。
|
||||
*/
|
||||
gRPCAGVServiceImpl();
|
||||
|
||||
// AGV服务接口
|
||||
grpc::Status GetStatusInfo(grpc::ServerContext* context,
|
||||
const api::GetAgvStatusInfoCommand_Request* request,
|
||||
api::GetAgvStatusInfoCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 默认析构函数。
|
||||
*/
|
||||
~gRPCAGVServiceImpl() override = default;
|
||||
|
||||
grpc::Status GetBatteryStatus(grpc::ServerContext* context,
|
||||
const api::RobotStatusBatteryCommand_Request* request,
|
||||
api::RobotStatusBatteryCommand_Feedback* response) override;
|
||||
// ===================== 基本状态查询接口 =====================
|
||||
|
||||
grpc::Status GetRobotLocation(grpc::ServerContext* context,
|
||||
const api::RobotStatusLocCommand_Request* request,
|
||||
api::RobotStatusLocCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 获取 AGV 基本信息(命令码 1000)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID(header.device_id)。
|
||||
* @param response 响应消息,填充 AGV 状态信息(版本、型号、IP、MAC 等)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status GetStatusInfo(grpc::ServerContext* context,
|
||||
const api::GetAgvStatusInfoCommand_Request* request,
|
||||
api::GetAgvStatusInfoCommand_Feedback* response) override;
|
||||
|
||||
grpc::Status RobotConfigDownloadMap(grpc::ServerContext* context,
|
||||
const api::RobotConfigDownloadMapCommand_Request* request,
|
||||
api::RobotConfigDownloadMapCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 查询电池状态(命令码 1007)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和可选的 simple 标志。
|
||||
* @param response 响应消息,填充电池电量、温度、充放电状态等。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status GetBatteryStatus(grpc::ServerContext* context,
|
||||
const api::RobotStatusBatteryCommand_Request* request,
|
||||
api::RobotStatusBatteryCommand_Feedback* response) override;
|
||||
|
||||
grpc::Status GetMapStatus(grpc::ServerContext* context,
|
||||
const api::RobotStatusMapCommand_Request* request,
|
||||
api::RobotStatusMapCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 查询机器人当前位置(命令码 1004)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID。
|
||||
* @param response 响应消息,填充坐标、朝向角、置信度、当前站点等。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status GetRobotLocation(grpc::ServerContext* context,
|
||||
const api::RobotStatusLocCommand_Request* request,
|
||||
api::RobotStatusLocCommand_Feedback* response) override;
|
||||
|
||||
grpc::Status RobotConfigUploadMap(grpc::ServerContext* context,
|
||||
const api::RobotConfigUploadMapCommand_Request* request,
|
||||
api::RobotConfigUploadMapCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief gRPC接口:抢占机器人控制权
|
||||
*/
|
||||
grpc::Status RobotConfigLock(grpc::ServerContext* context,
|
||||
const api::RobotConfigLockCommand_Request* request,
|
||||
api::RobotConfigLockCommand_Feedback* response) override;
|
||||
// ===================== 地图管理接口 =====================
|
||||
|
||||
/**
|
||||
* @brief 下载指定地图(命令码 4011)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和地图名称。
|
||||
* @param response 响应消息,返回地图 JSON 内容或错误码。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotConfigDownloadMap(grpc::ServerContext* context,
|
||||
const api::RobotConfigDownloadMapCommand_Request* request,
|
||||
api::RobotConfigDownloadMapCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 查询地图状态(命令码 1300)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID。
|
||||
* @param response 响应消息,返回当前地图名称、所有地图列表及文件详情。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status GetMapStatus(grpc::ServerContext* context,
|
||||
const api::RobotStatusMapCommand_Request* request,
|
||||
api::RobotStatusMapCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief gRPC接口 查询当前控制权持有者
|
||||
*/
|
||||
grpc::Status GetCurrentLockStatus(grpc::ServerContext* context,
|
||||
const api::RobotStatusCurrentLockCommand_Request* request,
|
||||
api::RobotStatusCurrentLockCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 上传地图(命令码 4010)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和完整的地图 JSON 字符串。
|
||||
* @param response 响应消息,返回上传结果(ret_code)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotConfigUploadMap(grpc::ServerContext* context,
|
||||
const api::RobotConfigUploadMapCommand_Request* request,
|
||||
api::RobotConfigUploadMapCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief AGV开环速度运动控制
|
||||
* @param context grpc上下文
|
||||
* @param request 请求体,header携带device_id区分多AGV
|
||||
* @param response 运动指令执行结果
|
||||
*/
|
||||
grpc::Status RobotMotionControl(grpc::ServerContext* context,
|
||||
const api::RobotMotionControlCommand_Request* request,
|
||||
api::RobotMotionControlCommand_Feedback* response) override;
|
||||
// ===================== 控制权管理接口 =====================
|
||||
|
||||
/**
|
||||
* @brief 抢占机器人控制权(命令码 4005)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和抢占者昵称。
|
||||
* @param response 响应消息,返回抢占结果(ret_code)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotConfigLock(grpc::ServerContext* context,
|
||||
const api::RobotConfigLockCommand_Request* request,
|
||||
api::RobotConfigLockCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 切换载入地图
|
||||
* @param context grpc上下文
|
||||
* @param request 请求体,携带目标地图名称
|
||||
* @param response 切换地图执行结果
|
||||
*/
|
||||
grpc::Status RobotLoadMap(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotLoadMapCommand_Request* request,
|
||||
api::RobotLoadMapCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 查询当前控制权持有者(命令码 1060)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID。
|
||||
* @param response 响应消息,返回是否被锁定、持有者 IP/端口/昵称等信息。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status GetCurrentLockStatus(grpc::ServerContext* context,
|
||||
const api::RobotStatusCurrentLockCommand_Request* request,
|
||||
api::RobotStatusCurrentLockCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 查询地图载入状态
|
||||
* @param context grpc上下文
|
||||
* @param request 请求头
|
||||
* @param response 地图加载状态结果
|
||||
*/
|
||||
grpc::Status QueryLoadMapStatus(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotQueryLoadMapStatusCommand_Request* request,
|
||||
api::RobotQueryLoadMapStatusCommand_Feedback* response) override;
|
||||
// ===================== 运动控制接口 =====================
|
||||
|
||||
/**
|
||||
* @brief 查询当前地图所有站点信息
|
||||
* @param context grpc上下文
|
||||
* @param request 请求头
|
||||
* @param response 站点列表结果
|
||||
*/
|
||||
grpc::Status QueryStationList(
|
||||
grpc::ServerContext* context,
|
||||
const api::QueryStationListCommand_Request* request,
|
||||
api::QueryStationListCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 下发开环速度运动指令(命令码 2010)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和速度参数(vx, vy, w, steer, duration 等)。
|
||||
* @param response 响应消息,返回指令下发结果(ret_code)。
|
||||
* @note 此指令会强制取消当前自动导航任务,多舵轮设备仅 vx/vy/w 生效。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotMotionControl(grpc::ServerContext* context,
|
||||
const api::RobotMotionControlCommand_Request* request,
|
||||
api::RobotMotionControlCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 切换载入地图(命令码 2022)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和目标地图名称。
|
||||
* @param response 响应消息,返回切换结果(ret_code)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotLoadMap(grpc::ServerContext* context,
|
||||
const api::RobotLoadMapCommand_Request* request,
|
||||
api::RobotLoadMapCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 指定路径连续站点导航
|
||||
* @param context grpc上下文
|
||||
* @param request 导航任务列表请求
|
||||
* @param response 下发任务返回结果
|
||||
*/
|
||||
grpc::Status RobotGoTargetList(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotGoTargetListCommand_Request* request,
|
||||
api::RobotGoTargetListCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 停止开环运动(命令码 2000)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID(无业务数据)。
|
||||
* @param response 响应消息,返回停止结果(ret_code)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotControlStop(grpc::ServerContext* context,
|
||||
const api::RobotControlStopCommand::Request* request,
|
||||
api::RobotControlStopCommand::Feedback* response) override;
|
||||
|
||||
// ===================== 导航任务接口 =====================
|
||||
|
||||
grpc::Status RobotStatusTask(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusTaskCommand_Request* request,
|
||||
api::RobotStatusTaskCommand_Feedback* response) override;
|
||||
/**
|
||||
* @brief 查询地图载入状态(命令码 1022)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID。
|
||||
* @param response 响应消息,返回 loadmap_status(0=失败, 1=成功, 2=载入中)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status QueryLoadMapStatus(grpc::ServerContext* context,
|
||||
const api::RobotQueryLoadMapStatusCommand_Request* request,
|
||||
api::RobotQueryLoadMapStatusCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 查询当前地图所有站点信息(命令码 1301)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID。
|
||||
* @param response 响应消息,返回站点列表(ID、坐标、类型等)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status QueryStationList(grpc::ServerContext* context,
|
||||
const api::QueryStationListCommand_Request* request,
|
||||
api::QueryStationListCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 指定路径导航(命令码 3066)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和多段导航任务列表(move_task_list)。
|
||||
* @param response 响应消息,返回下发结果(ret_code=0 仅表示接收成功,不表示执行完成)。
|
||||
* @attention 每个任务必须包含 task_id, source_id, id,且相邻站点间必须有直接路径。
|
||||
* 任务会排队执行,适合多车调度场景。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotGoTargetList(grpc::ServerContext* context,
|
||||
const api::RobotGoTargetListCommand_Request* request,
|
||||
api::RobotGoTargetListCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 查询当前实时导航状态(命令码 1020)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和 simple 标志。
|
||||
* @param response 响应消息,返回任务状态、任务类型、目标、路径等信息。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotStatusTaskCurrent(grpc::ServerContext* context,
|
||||
const api::RobotStatusTaskCurrentCommand_Request* request,
|
||||
api::RobotStatusTaskCurrentCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 批量查询任务状态(命令码 1110)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和 task_ids 列表(为空则查询所有未完成+最近完成)。
|
||||
* @param response 响应消息,返回任务状态包(进度、距离、各任务状态等)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotStatusTaskPackage(grpc::ServerContext* context,
|
||||
const api::RobotStatusTaskPackageCommand_Request* request,
|
||||
api::RobotStatusTaskPackageCommand_Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 单点站点自动规划导航(命令码 3051)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID 和完整的导航参数(支持自由导航、动作、PGV 等)。
|
||||
* @param response 响应消息,返回下发结果(ret_code=0 仅表示接收成功)。
|
||||
* @warning 严禁用于多车调度场景,仅限单车测试;新任务会取消当前任务(不排队)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotGoTarget(grpc::ServerContext* context,
|
||||
const api::RobotGoTargetCommand_Request* request,
|
||||
api::RobotGoTargetCommand_Feedback* response) override;
|
||||
|
||||
private:
|
||||
device::DeviceManager& dmgr_;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @brief 暂停当前导航任务(命令码 3001)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID(无业务数据)。
|
||||
* @param response 响应消息,返回暂停结果(ret_code)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotTaskPause(grpc::ServerContext* context,
|
||||
const api::RobotTaskPauseCommand::Request* request,
|
||||
api::RobotTaskPauseCommand::Feedback* response) override;
|
||||
|
||||
#endif //GRPC_AGV_SERVICE_H
|
||||
/**
|
||||
* @brief 继续当前导航任务(命令码 3002)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID(无业务数据)。
|
||||
* @param response 响应消息,返回继续结果(ret_code)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotTaskResume(grpc::ServerContext* context,
|
||||
const api::RobotTaskResumeCommand::Request* request,
|
||||
api::RobotTaskResumeCommand::Feedback* response) override;
|
||||
|
||||
/**
|
||||
* @brief 取消当前导航任务(命令码 3003)。
|
||||
* @param context gRPC 上下文(未使用)。
|
||||
* @param request 请求消息,包含设备 ID(无业务数据)。
|
||||
* @param response 响应消息,返回取消结果(ret_code)。
|
||||
* @return 始终返回 grpc::Status::OK,错误信息通过 response.header 返回。
|
||||
*/
|
||||
grpc::Status RobotTaskCancel(grpc::ServerContext* context,
|
||||
const api::RobotTaskCancelCommand::Request* request,
|
||||
api::RobotTaskCancelCommand::Feedback* response) override;
|
||||
|
||||
private:
|
||||
device::DeviceManager& dmgr_; ///< 设备管理器引用,用于根据 device_id 获取 AGV 设备实例。
|
||||
};
|
||||
|
||||
} // namespace cmvr::service
|
||||
|
||||
#endif // GRPC_AGV_SERVICE_H
|
||||
@ -1,6 +1,15 @@
|
||||
//
|
||||
// Created by xtkuang on 2025/6/1.
|
||||
//
|
||||
/**
|
||||
* @file grpc_agv_service.cpp
|
||||
* @brief gRPC AGV 服务实现。
|
||||
* 每个 RPC 方法从请求头中提取 device_id,通过 DeviceManager 获取对应的 AGV 设备,
|
||||
* 调用设备层的具体方法,并将结果转换为 Protobuf 响应。
|
||||
* 统一处理异常,设置响应头中的 success/error_message 和时间戳。
|
||||
* @author xtkuang
|
||||
* @date 2025-06-01
|
||||
*/
|
||||
|
||||
#include "./service/grpc/include/grpc_agv_service.h"
|
||||
|
||||
@ -12,9 +21,21 @@
|
||||
|
||||
namespace cmvr::service {
|
||||
|
||||
/**
|
||||
* @brief 构造函数,获取 DeviceManager 单例。
|
||||
*/
|
||||
gRPCAGVServiceImpl::gRPCAGVServiceImpl() : dmgr_(device::DeviceManager::getInstance()) {
|
||||
}
|
||||
|
||||
// ===================== GetStatusInfo =====================
|
||||
/**
|
||||
* @brief 获取 AGV 基本信息。
|
||||
* @details 从请求中提取 device_id,调用设备层的 getStatusInfo,填充响应。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回状态信息和响应头。
|
||||
* @return 始终返回 OK,错误通过 response.header 传递。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::GetStatusInfo(
|
||||
grpc::ServerContext* context,
|
||||
const api::GetAgvStatusInfoCommand_Request* request,
|
||||
@ -28,6 +49,7 @@ namespace cmvr::service {
|
||||
device::AbstractAgv::AgvStatusInfo device_status;
|
||||
agv_device->getStatusInfo(device_status);
|
||||
|
||||
// 映射到 Protobuf 消息
|
||||
auto* proto_status = response->mutable_status();
|
||||
proto_status->set_id(device_status.id);
|
||||
proto_status->set_vehicle_id(device_status.vehicle_id);
|
||||
@ -58,62 +80,75 @@ namespace cmvr::service {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
grpc::Status gRPCAGVServiceImpl::GetBatteryStatus(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusBatteryCommand_Request* request,
|
||||
api::RobotStatusBatteryCommand_Feedback* response)
|
||||
{
|
||||
try {
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (GetBatteryStatus): id=" << dev_id;
|
||||
const auto agv_device = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
bool simple = false;
|
||||
if (request->has_data())
|
||||
{
|
||||
simple = request->data().simple();
|
||||
}
|
||||
|
||||
device::AbstractAgv::BatteryStatus bat_info;
|
||||
agv_device->getBatteryStatus(bat_info, simple);
|
||||
|
||||
auto* proto_bat = response->mutable_status();
|
||||
proto_bat->set_battery_level(bat_info.battery_level);
|
||||
proto_bat->set_battery_temp(bat_info.battery_temp);
|
||||
proto_bat->set_charging(bat_info.charging);
|
||||
proto_bat->set_voltage(bat_info.voltage);
|
||||
proto_bat->set_current(bat_info.current);
|
||||
proto_bat->set_max_charge_voltage(bat_info.max_charge_voltage);
|
||||
proto_bat->set_max_charge_current(bat_info.max_charge_current);
|
||||
proto_bat->set_manual_charge(bat_info.manual_charge);
|
||||
proto_bat->set_auto_charge(bat_info.auto_charge);
|
||||
proto_bat->set_battery_cycle(bat_info.battery_cycle);
|
||||
proto_bat->set_battery_user_data(bat_info.battery_user_data);
|
||||
proto_bat->set_extra(bat_info.extra);
|
||||
proto_bat->set_ret_code(bat_info.ret_code);
|
||||
proto_bat->set_create_on(bat_info.create_on);
|
||||
proto_bat->set_err_msg(bat_info.err_msg);
|
||||
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(true);
|
||||
header->set_error_message("");
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "GetBatteryStatus device_id:" << dev_id << " level: " << bat_info.battery_level;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
// ===================== GetBatteryStatus =====================
|
||||
/**
|
||||
* @brief 查询电池状态。
|
||||
* @details 支持 simple 参数,调用设备层 getBatteryStatus。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和 simple 标志。
|
||||
* @param response 返回电池信息。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::GetBatteryStatus(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusBatteryCommand_Request* request,
|
||||
api::RobotStatusBatteryCommand_Feedback* response)
|
||||
{
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message(e.what());
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
try {
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (GetBatteryStatus): id=" << dev_id;
|
||||
const auto agv_device = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
bool simple = false;
|
||||
if (request->has_data())
|
||||
{
|
||||
simple = request->data().simple();
|
||||
}
|
||||
|
||||
device::AbstractAgv::BatteryStatus bat_info;
|
||||
agv_device->getBatteryStatus(bat_info, simple);
|
||||
|
||||
auto* proto_bat = response->mutable_status();
|
||||
proto_bat->set_battery_level(bat_info.battery_level);
|
||||
proto_bat->set_battery_temp(bat_info.battery_temp);
|
||||
proto_bat->set_charging(bat_info.charging);
|
||||
proto_bat->set_voltage(bat_info.voltage);
|
||||
proto_bat->set_current(bat_info.current);
|
||||
proto_bat->set_max_charge_voltage(bat_info.max_charge_voltage);
|
||||
proto_bat->set_max_charge_current(bat_info.max_charge_current);
|
||||
proto_bat->set_manual_charge(bat_info.manual_charge);
|
||||
proto_bat->set_auto_charge(bat_info.auto_charge);
|
||||
proto_bat->set_battery_cycle(bat_info.battery_cycle);
|
||||
proto_bat->set_battery_user_data(bat_info.battery_user_data);
|
||||
proto_bat->set_extra(bat_info.extra);
|
||||
proto_bat->set_ret_code(bat_info.ret_code);
|
||||
proto_bat->set_create_on(bat_info.create_on);
|
||||
proto_bat->set_err_msg(bat_info.err_msg);
|
||||
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(true);
|
||||
header->set_error_message("");
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "GetBatteryStatus device_id:" << dev_id << " level: " << bat_info.battery_level;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message(e.what());
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================== GetRobotLocation =====================
|
||||
/**
|
||||
* @brief 查询机器人当前位置。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回坐标、朝向、置信度等。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::GetRobotLocation(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusLocCommand_Request* request,
|
||||
@ -157,7 +192,13 @@ api::RobotStatusBatteryCommand_Feedback* response)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================== RobotConfigDownloadMap =====================
|
||||
/**
|
||||
* @brief 下载指定地图。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和地图名称。
|
||||
* @param response 返回地图 JSON 内容或错误码。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotConfigDownloadMap(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotConfigDownloadMapCommand_Request* request,
|
||||
@ -196,8 +237,13 @@ api::RobotStatusBatteryCommand_Feedback* response)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ===================== GetMapStatus =====================
|
||||
/**
|
||||
* @brief 查询地图状态。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回当前地图、地图列表及文件详情。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::GetMapStatus(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusMapCommand_Request* request,
|
||||
@ -249,7 +295,13 @@ api::RobotStatusBatteryCommand_Feedback* response)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================== RobotConfigUploadMap =====================
|
||||
/**
|
||||
* @brief 上传地图。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和地图 JSON 字符串。
|
||||
* @param response 返回上传结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotConfigUploadMap(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotConfigUploadMapCommand_Request* request,
|
||||
@ -287,39 +339,33 @@ api::RobotStatusBatteryCommand_Feedback* response)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================== RobotConfigLock =====================
|
||||
/**
|
||||
* @brief gRPC 抢占机器人控制权接口
|
||||
* @param context grpc上下文
|
||||
* @param request 前端请求参数,携带nick_name抢占者名称
|
||||
* @param response 抢占结果返回体
|
||||
*/
|
||||
* @brief 抢占机器人控制权。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和抢占者昵称。
|
||||
* @param response 返回抢占结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotConfigLock(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotConfigLockCommand_Request* request,
|
||||
api::RobotConfigLockCommand_Feedback* response)
|
||||
{
|
||||
try {
|
||||
// 动态从header拿设备ID,和查询接口统一
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (RobotConfigLock): id=" << dev_id;
|
||||
|
||||
// 根据device_id获取对应AGV实例
|
||||
const auto agv_device = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
// 读取抢占者名称
|
||||
std::string nick_name = request->data().nick_name();
|
||||
device::AbstractAgv::LockResult lock_res;
|
||||
// 调用底层抢占接口
|
||||
agv_device->lockRobotControl(lock_res, nick_name);
|
||||
|
||||
// 填充protobuf返回数据
|
||||
auto* proto_status = response->mutable_status();
|
||||
proto_status->set_ret_code(lock_res.ret_code);
|
||||
proto_status->set_create_on(lock_res.create_on);
|
||||
proto_status->set_err_msg(lock_res.err_msg);
|
||||
|
||||
// 响应头标记成功 + 时间戳对齐全局规范
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(true);
|
||||
header->set_error_message("");
|
||||
@ -330,7 +376,6 @@ api::RobotStatusBatteryCommand_Feedback* response)
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
// 统一异常捕获,和相机/查询接口风格完全一致
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message(e.what());
|
||||
@ -339,71 +384,72 @@ api::RobotStatusBatteryCommand_Feedback* response)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 查询机器人当前控制权信息gRPC接口
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
// ===================== GetCurrentLockStatus =====================
|
||||
/**
|
||||
* @brief 查询当前控制权持有者。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回锁定状态、持有者信息等。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusCurrentLockCommand_Request* request,
|
||||
api::RobotStatusCurrentLockCommand_Feedback* response)
|
||||
{
|
||||
try {
|
||||
// 1. 读取请求device_id,打印日志(和相机代码保持一致)
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (GetCurrentLockStatus): id=" << dev_id;
|
||||
|
||||
// 2. 按device_id获取AGV设备实例,和相机 dmgr_.getDevice<AbstractCamera>(dev_id) 统一写法
|
||||
const auto agv_dev = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
// 3. 调用底层接口获取控制权信息
|
||||
device::AbstractAgv::CurrentLockStatus lock_info;
|
||||
agv_dev->getCurrentLockStatus(lock_info);
|
||||
|
||||
// 4. 填充protobuf返回结构体
|
||||
auto* proto_status = response->mutable_status();
|
||||
proto_status->set_locked(lock_info.locked);
|
||||
proto_status->set_ip(lock_info.ip);
|
||||
proto_status->set_port(lock_info.port);
|
||||
proto_status->set_type(lock_info.type);
|
||||
proto_status->set_nick_name(lock_info.nick_name);
|
||||
proto_status->set_time_t(lock_info.time_t);
|
||||
proto_status->set_desc(lock_info.desc);
|
||||
proto_status->set_ret_code(lock_info.ret_code);
|
||||
proto_status->set_create_on(lock_info.create_on);
|
||||
proto_status->set_err_msg(lock_info.err_msg);
|
||||
|
||||
// 5. 响应header标记成功 + 填充时间戳(对齐相机接口)
|
||||
response->mutable_header()->set_success(true);
|
||||
setCurrentTimestamp(response->mutable_header()->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "Query current lock status, device_id:" << dev_id
|
||||
<< ", locked:" << lock_info.locked << ", nick:" << lock_info.nick_name;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
// 异常统一捕获,失败header,填错误信息+时间戳,和相机完全对齐
|
||||
response->mutable_header()->set_success(false);
|
||||
response->mutable_header()->set_error_message(e.what());
|
||||
setCurrentTimestamp(response->mutable_header()->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
try {
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (GetCurrentLockStatus): id=" << dev_id;
|
||||
|
||||
const auto agv_dev = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
device::AbstractAgv::CurrentLockStatus lock_info;
|
||||
agv_dev->getCurrentLockStatus(lock_info);
|
||||
|
||||
auto* proto_status = response->mutable_status();
|
||||
proto_status->set_locked(lock_info.locked);
|
||||
proto_status->set_ip(lock_info.ip);
|
||||
proto_status->set_port(lock_info.port);
|
||||
proto_status->set_type(lock_info.type);
|
||||
proto_status->set_nick_name(lock_info.nick_name);
|
||||
proto_status->set_time_t(lock_info.time_t);
|
||||
proto_status->set_desc(lock_info.desc);
|
||||
proto_status->set_ret_code(lock_info.ret_code);
|
||||
proto_status->set_create_on(lock_info.create_on);
|
||||
proto_status->set_err_msg(lock_info.err_msg);
|
||||
|
||||
response->mutable_header()->set_success(true);
|
||||
setCurrentTimestamp(response->mutable_header()->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "Query current lock status, device_id:" << dev_id
|
||||
<< ", locked:" << lock_info.locked << ", nick:" << lock_info.nick_name;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
response->mutable_header()->set_success(false);
|
||||
response->mutable_header()->set_error_message(e.what());
|
||||
setCurrentTimestamp(response->mutable_header()->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================== RobotMotionControl =====================
|
||||
/**
|
||||
* @brief 开环速度运动控制。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和速度参数。
|
||||
* @param response 返回指令下发结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotMotionControl(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotMotionControlCommand_Request* request,
|
||||
api::RobotMotionControlCommand_Feedback* response)
|
||||
{
|
||||
try {
|
||||
// 从header读取device_id,区分多台AGV设备
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (RobotMotionControl): target device_id=" << dev_id;
|
||||
const auto agv_dev = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
// grpc入参转换到底层结构体
|
||||
device::AbstractAgv::MotionCtrlReq req;
|
||||
auto& input_data = request->data();
|
||||
req.vx = input_data.vx();
|
||||
@ -413,17 +459,14 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
req.real_steer = input_data.real_steer();
|
||||
req.duration = input_data.duration();
|
||||
|
||||
// 调用底层运动控制接口
|
||||
device::AbstractAgv::MotionCtrlRes res;
|
||||
agv_dev->robotMotionControl(res, req);
|
||||
|
||||
// 填充grpc返回状态
|
||||
auto* resp_status = response->mutable_status();
|
||||
resp_status->set_ret_code(res.ret_code);
|
||||
resp_status->set_create_on(res.create_on);
|
||||
resp_status->set_err_msg(res.err_msg);
|
||||
|
||||
// 统一规范header:成功标记+时间戳
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(true);
|
||||
header->set_error_message("");
|
||||
@ -436,7 +479,6 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// 全局统一异常捕获模板
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message(e.what());
|
||||
@ -445,6 +487,13 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== RobotLoadMap =====================
|
||||
/**
|
||||
* @brief 切换载入地图。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和目标地图名称。
|
||||
* @param response 返回切换结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotLoadMap(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotLoadMapCommand_Request* request,
|
||||
@ -470,7 +519,6 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(true);
|
||||
header->set_error_message("");
|
||||
// 修复:取timestamp子字段
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "RobotLoadMap finish, dev_id:" << dev_id
|
||||
@ -483,13 +531,18 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message(e.what());
|
||||
// 修复:取timestamp子字段
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================== QueryLoadMapStatus =====================
|
||||
/**
|
||||
* @brief 查询地图载入状态。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回 loadmap_status。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::QueryLoadMapStatus(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotQueryLoadMapStatusCommand_Request* request,
|
||||
@ -529,6 +582,13 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== QueryStationList =====================
|
||||
/**
|
||||
* @brief 查询当前地图所有站点信息。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回站点列表。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::QueryStationList(
|
||||
grpc::ServerContext* context,
|
||||
const api::QueryStationListCommand_Request* request,
|
||||
@ -547,7 +607,6 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
resp_status->set_create_on(res.create_on);
|
||||
resp_status->set_err_msg(res.err_msg);
|
||||
|
||||
// 填充站点数组
|
||||
for (auto& st : res.stations)
|
||||
{
|
||||
auto* pb_st = resp_status->add_stations();
|
||||
@ -584,7 +643,13 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===================== RobotGoTargetList =====================
|
||||
/**
|
||||
* @brief 指定路径导航(多点)。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和 move_task_list。
|
||||
* @param response 返回下发结果(仅表示指令被接收)。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotGoTargetList(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotGoTargetListCommand_Request* request,
|
||||
@ -636,28 +701,31 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
grpc::Status gRPCAGVServiceImpl::RobotStatusTask(
|
||||
// ===================== RobotStatusTaskCurrent =====================
|
||||
/**
|
||||
* @brief 查询当前实时导航状态。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和 simple 标志。
|
||||
* @param response 返回任务状态、类型、目标、路径等。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotStatusTaskCurrent(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusTaskCommand_Request* request,
|
||||
api::RobotStatusTaskCommand_Feedback* response)
|
||||
const api::RobotStatusTaskCurrentCommand_Request* request,
|
||||
api::RobotStatusTaskCurrentCommand_Feedback* response)
|
||||
{
|
||||
try {
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (RobotStatusTask): id=" << dev_id;
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (RobotStatusTaskCurrent): id=" << dev_id;
|
||||
const auto agv_dev = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
// 嵌套结构体 必须加 AbstractAgv::
|
||||
device::AbstractAgv::RobotStatusTaskReq req;
|
||||
device::AbstractAgv::RobotStatusTaskCurrentReq req;
|
||||
if (request->has_data())
|
||||
{
|
||||
req.simple = request->data().simple();
|
||||
}
|
||||
|
||||
device::AbstractAgv::RobotStatusTaskRes res;
|
||||
agv_dev->robotStatusTask(res, req);
|
||||
device::AbstractAgv::RobotStatusTaskCurrentRes res;
|
||||
agv_dev->robotStatusTaskCurrent(res, req);
|
||||
|
||||
auto* out_data = response->mutable_data();
|
||||
out_data->set_ret_code(res.ret_code);
|
||||
@ -690,7 +758,7 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
header->set_error_message("");
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "RobotStatusTask device_id:" << dev_id << " task_status: " << res.task_status;
|
||||
LOG(INFO) << "RobotStatusTaskCurrent dev_id:" << dev_id << " task_status:" << res.task_status;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
@ -703,6 +771,438 @@ grpc::Status gRPCAGVServiceImpl::GetCurrentLockStatus(
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== RobotStatusTaskPackage =====================
|
||||
/**
|
||||
* @brief 批量查询任务状态。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和 task_ids 列表。
|
||||
* @param response 返回任务状态包(进度、距离、每个任务状态等)。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotStatusTaskPackage(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotStatusTaskPackageCommand_Request* request,
|
||||
api::RobotStatusTaskPackageCommand_Feedback* response)
|
||||
{
|
||||
try {
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[gRPCAGVServiceImpl] (RobotStatusTaskPackage): id=" << dev_id;
|
||||
const auto agv_dev = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
|
||||
device::AbstractAgv::QueryTaskStatusPackageReq req;
|
||||
const auto& pb_ids = request->data().task_ids();
|
||||
for (auto& tid : pb_ids)
|
||||
{
|
||||
req.task_ids.push_back(tid);
|
||||
}
|
||||
|
||||
}
|
||||
device::AbstractAgv::QueryTaskStatusPackageRes res;
|
||||
agv_dev->robotStatusTaskPackage(res, req);
|
||||
|
||||
auto* out_data = response->mutable_data();
|
||||
out_data->set_ret_code(res.ret_code);
|
||||
out_data->set_create_on(res.create_on);
|
||||
out_data->set_err_msg(res.err_msg);
|
||||
|
||||
auto* pkg_pb = out_data->mutable_task_status_package();
|
||||
auto& pkg_data = res.task_status_package;
|
||||
pkg_pb->set_closest_target(pkg_data.closest_target);
|
||||
pkg_pb->set_source_name(pkg_data.source_name);
|
||||
pkg_pb->set_target_name(pkg_data.target_name);
|
||||
pkg_pb->set_percentage(pkg_data.percentage);
|
||||
pkg_pb->set_distance(pkg_data.distance);
|
||||
pkg_pb->set_info(pkg_data.info);
|
||||
|
||||
for (auto& st_item : pkg_data.task_status_list)
|
||||
{
|
||||
auto* st_pb = pkg_pb->add_task_status_list();
|
||||
st_pb->set_task_id(st_item.task_id);
|
||||
st_pb->set_status(st_item.status);
|
||||
st_pb->set_type(st_item.type);
|
||||
}
|
||||
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(true);
|
||||
header->set_error_message("");
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "RobotStatusTaskPackage dev_id:" << dev_id << " query task count:" << req.task_ids.size() << " ret_code:" << res.ret_code;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message(e.what());
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== RobotGoTarget =====================
|
||||
/**
|
||||
* @brief 单点站点自动规划导航。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID 和完整的导航参数(支持自由导航、动作、PGV、脚本等)。
|
||||
* @param response 返回下发结果。
|
||||
* @warning 严禁用于多车调度场景,仅限单车测试。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotGoTarget(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotGoTargetCommand_Request* request,
|
||||
api::RobotGoTargetCommand_Feedback* response)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string dev_id = request->header().device_id();
|
||||
LOG(INFO) << "[RobotGoTarget] device_id:" << dev_id;
|
||||
auto agv_dev = dmgr_.getDevice<device::AbstractAgv>(dev_id);
|
||||
if (!agv_dev)
|
||||
{
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message("device not found");
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
device::AbstractAgv::RobotGoTargetReq req;
|
||||
auto& pb_data = request->data();
|
||||
|
||||
// -------- 必填字段 --------
|
||||
req.source_id = pb_data.source_id();
|
||||
req.id = pb_data.id();
|
||||
if (pb_data.has_task_id()) req.task_id = pb_data.task_id();
|
||||
|
||||
// -------- 运动参数 --------
|
||||
if (pb_data.has_angle()) req.angle = pb_data.angle();
|
||||
if (pb_data.has_method()) req.method = pb_data.method();
|
||||
if (pb_data.has_max_speed()) req.max_speed = pb_data.max_speed();
|
||||
if (pb_data.has_max_wspeed()) req.max_wspeed = pb_data.max_wspeed();
|
||||
if (pb_data.has_max_acc()) req.max_acc = pb_data.max_acc();
|
||||
if (pb_data.has_max_wacc()) req.max_wacc = pb_data.max_wacc();
|
||||
if (pb_data.has_duration()) req.duration = pb_data.duration();
|
||||
if (pb_data.has_orientation()) req.orientation = pb_data.orientation();
|
||||
if (pb_data.has_spin()) req.spin = pb_data.spin();
|
||||
if (pb_data.has_delay()) req.delay = pb_data.delay();
|
||||
if (pb_data.has_start_rot_dir()) req.start_rot_dir = pb_data.start_rot_dir();
|
||||
if (pb_data.has_end_rot_dir()) req.end_rot_dir = pb_data.end_rot_dir();
|
||||
if (pb_data.has_reach_dist()) req.reach_dist = pb_data.reach_dist();
|
||||
if (pb_data.has_reach_angle()) req.reach_angle = pb_data.reach_angle();
|
||||
if (pb_data.has_skill_name()) req.skill_name = pb_data.skill_name();
|
||||
|
||||
// -------- PGV 二次定位 --------
|
||||
if (pb_data.has_pgv())
|
||||
{
|
||||
auto& pgv_pb = pb_data.pgv();
|
||||
req.pgv.use_pgv = pgv_pb.use_pgv();
|
||||
req.pgv.use_down_pgv = pgv_pb.use_down_pgv();
|
||||
if (pgv_pb.has_pgv_adjust_dist()) req.pgv.pgv_adjust_dist = pgv_pb.pgv_adjust_dist();
|
||||
if (pgv_pb.has_pgv_adjust_cx()) req.pgv.pgv_adjust_cx = pgv_pb.pgv_adjust_cx();
|
||||
if (pgv_pb.has_pgv_adjust_cy()) req.pgv.pgv_adjust_cy = pgv_pb.pgv_adjust_cy();
|
||||
if (pgv_pb.has_pgv_x_adjust()) req.pgv.pgv_x_adjust = pgv_pb.pgv_x_adjust();
|
||||
}
|
||||
|
||||
// -------- 设备动作 --------
|
||||
if (pb_data.has_operation()) req.operation = pb_data.operation();
|
||||
if (pb_data.has_jack_height()) req.jack_height = pb_data.jack_height();
|
||||
if (pb_data.has_start_height()) req.start_height = pb_data.start_height();
|
||||
if (pb_data.has_end_height()) req.end_height = pb_data.end_height();
|
||||
if (pb_data.has_fork_mid_height()) req.fork_mid_height = pb_data.fork_mid_height();
|
||||
if (pb_data.has_fork_dist()) req.fork_dist = pb_data.fork_dist();
|
||||
if (pb_data.has_direction()) req.direction = pb_data.direction();
|
||||
if (pb_data.has_recognize()) req.recognize = pb_data.recognize();
|
||||
if (pb_data.has_recfile()) req.recfile = pb_data.recfile();
|
||||
|
||||
// -------- 音频 --------
|
||||
if (pb_data.has_sounds_args())
|
||||
{
|
||||
auto& s_pb = pb_data.sounds_args();
|
||||
if (s_pb.has_name()) req.sounds_args.name = s_pb.name();
|
||||
if (s_pb.has_loop()) req.sounds_args.loop = s_pb.loop();
|
||||
if (s_pb.has_stop()) req.sounds_args.stop = s_pb.stop();
|
||||
}
|
||||
|
||||
// -------- WaitDI --------
|
||||
if (pb_data.has_wait_di_args())
|
||||
{
|
||||
auto& di_pb = pb_data.wait_di_args();
|
||||
req.wait_di_args.timeout = di_pb.timeout();
|
||||
for (auto& item : di_pb.di())
|
||||
{
|
||||
device::AbstractAgv::DIItem di;
|
||||
di.id = item.id();
|
||||
di.status = item.status();
|
||||
req.wait_di_args.DI.push_back(di);
|
||||
}
|
||||
}
|
||||
|
||||
// -------- SetDO --------
|
||||
if (pb_data.has_set_do_args())
|
||||
{
|
||||
auto& do_pb = pb_data.set_do_args();
|
||||
for (auto& item : do_pb.do_list())
|
||||
{
|
||||
device::AbstractAgv::DOItem d;
|
||||
d.id = item.id();
|
||||
d.status = item.status();
|
||||
req.set_do_args.DO.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
// -------- 脚本 --------
|
||||
if (pb_data.has_script_name()) req.script_name = pb_data.script_name();
|
||||
if (pb_data.has_script_stage()) req.script_stage = pb_data.script_stage();
|
||||
if (pb_data.has_script_args())
|
||||
{
|
||||
auto& s_arg_pb = pb_data.script_args();
|
||||
for (auto& kv : s_arg_pb.str_kv()) req.script_args.str_kv[kv.first] = kv.second;
|
||||
for (auto& kv : s_arg_pb.num_kv()) req.script_args.num_kv[kv.first] = kv.second;
|
||||
for (auto& d : s_arg_pb.do_list())
|
||||
{
|
||||
device::AbstractAgv::DOItem di;
|
||||
di.id = d.id();
|
||||
di.status = d.status();
|
||||
req.script_args.do_list.push_back(di);
|
||||
}
|
||||
for (auto& di : s_arg_pb.di_list())
|
||||
{
|
||||
device::AbstractAgv::DIItem d;
|
||||
d.id = di.id();
|
||||
d.status = di.status();
|
||||
req.script_args.di_list.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
// -------- 原地旋转 --------
|
||||
if (pb_data.has_move_angle()) req.move_angle = pb_data.move_angle();
|
||||
if (pb_data.has_speed_w()) req.speed_w = pb_data.speed_w();
|
||||
if (pb_data.has_loc_mode()) req.loc_mode = pb_data.loc_mode();
|
||||
|
||||
// -------- 自由导航 --------
|
||||
if (pb_data.has_freego())
|
||||
{
|
||||
auto& fg_pb = pb_data.freego();
|
||||
req.freeGo.x = fg_pb.x();
|
||||
req.freeGo.y = fg_pb.y();
|
||||
req.freeGo.theta = fg_pb.theta();
|
||||
}
|
||||
|
||||
// 调用设备层
|
||||
device::AbstractAgv::RobotGoTargetRes res;
|
||||
agv_dev->robotGoTarget(res, req);
|
||||
|
||||
auto* out_data = response->mutable_data();
|
||||
out_data->set_ret_code(res.ret_code);
|
||||
out_data->set_create_on(res.create_on);
|
||||
out_data->set_err_msg(res.err_msg);
|
||||
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(true);
|
||||
header->set_error_message("");
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
|
||||
LOG(INFO) << "[RobotGoTarget] finish ret_code=" << res.ret_code;
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
auto* header = response->mutable_header();
|
||||
header->set_success(false);
|
||||
header->set_error_message(std::string("exception:") + e.what());
|
||||
setCurrentTimestamp(header->mutable_timestamp());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== RobotControlStop =====================
|
||||
/**
|
||||
* @brief 停止开环运动。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID(无业务数据)。
|
||||
* @param response 返回停止结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotControlStop(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotControlStopCommand::Request* request,
|
||||
api::RobotControlStopCommand::Feedback* response) {
|
||||
|
||||
const auto& header = request->header();
|
||||
std::string device_id = header.device_id();
|
||||
auto* fb_header = response->mutable_header();
|
||||
|
||||
if (device_id.empty()) {
|
||||
fb_header->set_error_message("Missing device_id");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto agv = dmgr_.getDevice<cmvr::device::AbstractAgv>(device_id);
|
||||
if (!agv) {
|
||||
fb_header->set_error_message("Device not found or not an AGV");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
cmvr::device::AbstractAgv::RobotControlStopRes res;
|
||||
agv->robotControlStop(res);
|
||||
|
||||
auto* status = response->mutable_status();
|
||||
status->set_ret_code(res.ret_code);
|
||||
status->set_create_on(res.create_on);
|
||||
status->set_err_msg(res.err_msg);
|
||||
|
||||
if (res.ret_code == 0) {
|
||||
fb_header->set_error_message("");
|
||||
} else {
|
||||
fb_header->set_error_message(res.err_msg.empty() ? "Stop motion failed" : res.err_msg);
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
// ===================== RobotTaskPause =====================
|
||||
/**
|
||||
* @brief 暂停当前导航任务。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回暂停结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotTaskPause(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotTaskPauseCommand::Request* request,
|
||||
api::RobotTaskPauseCommand::Feedback* response) {
|
||||
|
||||
const auto& header = request->header();
|
||||
std::string device_id = header.device_id();
|
||||
auto* fb_header = response->mutable_header();
|
||||
|
||||
if (device_id.empty()) {
|
||||
fb_header->set_error_message("Missing device_id");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto agv = dmgr_.getDevice<cmvr::device::AbstractAgv>(device_id);
|
||||
if (!agv) {
|
||||
fb_header->set_error_message("Device not found or not an AGV");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
cmvr::device::AbstractAgv::RobotTaskPauseRes res;
|
||||
try {
|
||||
agv->robotTaskPause(res);
|
||||
} catch (const std::exception& e) {
|
||||
fb_header->set_error_message(std::string("Exception: ") + e.what());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto* status = response->mutable_status();
|
||||
status->set_ret_code(res.ret_code);
|
||||
status->set_create_on(res.create_on);
|
||||
status->set_err_msg(res.err_msg);
|
||||
|
||||
if (res.ret_code != 0) {
|
||||
fb_header->set_error_message(res.err_msg.empty() ? "Pause task failed" : res.err_msg);
|
||||
} else {
|
||||
fb_header->set_error_message("");
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
// ===================== RobotTaskResume =====================
|
||||
/**
|
||||
* @brief 继续当前导航任务。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回继续结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotTaskResume(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotTaskResumeCommand::Request* request,
|
||||
api::RobotTaskResumeCommand::Feedback* response) {
|
||||
|
||||
const auto& header = request->header();
|
||||
std::string device_id = header.device_id();
|
||||
auto* fb_header = response->mutable_header();
|
||||
|
||||
if (device_id.empty()) {
|
||||
fb_header->set_error_message("Missing device_id");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto agv = dmgr_.getDevice<cmvr::device::AbstractAgv>(device_id);
|
||||
if (!agv) {
|
||||
fb_header->set_error_message("Device not found or not an AGV");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
cmvr::device::AbstractAgv::RobotTaskResumeRes res;
|
||||
try {
|
||||
agv->robotTaskResume(res);
|
||||
} catch (const std::exception& e) {
|
||||
fb_header->set_error_message(std::string("Exception: ") + e.what());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto* status = response->mutable_status();
|
||||
status->set_ret_code(res.ret_code);
|
||||
status->set_create_on(res.create_on);
|
||||
status->set_err_msg(res.err_msg);
|
||||
|
||||
if (res.ret_code != 0) {
|
||||
fb_header->set_error_message(res.err_msg.empty() ? "Resume task failed" : res.err_msg);
|
||||
} else {
|
||||
fb_header->set_error_message("");
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
// ===================== RobotTaskCancel =====================
|
||||
/**
|
||||
* @brief 取消当前导航任务。
|
||||
* @param context 未使用。
|
||||
* @param request 包含设备 ID。
|
||||
* @param response 返回取消结果。
|
||||
*/
|
||||
grpc::Status gRPCAGVServiceImpl::RobotTaskCancel(
|
||||
grpc::ServerContext* context,
|
||||
const api::RobotTaskCancelCommand::Request* request,
|
||||
api::RobotTaskCancelCommand::Feedback* response) {
|
||||
|
||||
const auto& header = request->header();
|
||||
std::string device_id = header.device_id();
|
||||
auto* fb_header = response->mutable_header();
|
||||
|
||||
if (device_id.empty()) {
|
||||
fb_header->set_error_message("Missing device_id");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto agv = dmgr_.getDevice<cmvr::device::AbstractAgv>(device_id);
|
||||
if (!agv) {
|
||||
fb_header->set_error_message("Device not found or not an AGV");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
cmvr::device::AbstractAgv::RobotTaskCancelRes res;
|
||||
try {
|
||||
agv->robotTaskCancel(res);
|
||||
} catch (const std::exception& e) {
|
||||
fb_header->set_error_message(std::string("Exception: ") + e.what());
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto* status = response->mutable_status();
|
||||
status->set_ret_code(res.ret_code);
|
||||
status->set_create_on(res.create_on);
|
||||
status->set_err_msg(res.err_msg);
|
||||
|
||||
if (res.ret_code != 0) {
|
||||
fb_header->set_error_message(res.err_msg.empty() ? "Cancel task failed" : res.err_msg);
|
||||
} else {
|
||||
fb_header->set_error_message("");
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
} // namespace cmvr::service
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,8 @@
|
||||
/**
|
||||
* @file agv_service.proto
|
||||
* @brief 定义AGV服务的gRPC接口,聚合所有AGV相关命令。
|
||||
* 服务端实现类为 gRPCAGVServiceImpl。
|
||||
*/
|
||||
syntax = "proto3";
|
||||
|
||||
import "cmvr/api/agv_command.proto";
|
||||
@ -45,16 +50,25 @@ service AgvService {
|
||||
rpc RobotGoTargetList(RobotGoTargetListCommand.Request) returns (RobotGoTargetListCommand.Feedback);
|
||||
|
||||
// 查询当前导航状态 1020 robot_status_task_req
|
||||
rpc RobotStatusTask(RobotStatusTaskCommand.Request) returns (RobotStatusTaskCommand.Feedback);
|
||||
// 1020 查询当前实时导航 robot_status_task_req
|
||||
rpc RobotStatusTaskCurrent(RobotStatusTaskCurrentCommand.Request) returns (RobotStatusTaskCurrentCommand.Feedback);
|
||||
|
||||
// 批量查询任务状态 1110 robot_status_task_status_package_req
|
||||
rpc RobotStatusTaskPackage(RobotStatusTaskPackageCommand.Request) returns (RobotStatusTaskPackageCommand.Feedback);
|
||||
|
||||
|
||||
// 3051 单点站点自动规划导航 robot_task_gotarget_req 0x0BEB
|
||||
rpc RobotGoTarget(RobotGoTargetCommand.Request) returns (RobotGoTargetCommand.Feedback);
|
||||
|
||||
|
||||
|
||||
// 0x07D0 停止开环运动
|
||||
rpc RobotControlStop(RobotControlStopCommand.Request) returns (RobotControlStopCommand.Feedback);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 暂停当前导航任务 命令码 3001 (0x0BB9)
|
||||
rpc RobotTaskPause(RobotTaskPauseCommand.Request) returns (RobotTaskPauseCommand.Feedback);
|
||||
// 继续当前导航任务 命令码 3002 (0x0BBA)
|
||||
rpc RobotTaskResume(RobotTaskResumeCommand.Request) returns (RobotTaskResumeCommand.Feedback);
|
||||
// 取消当前导航任务 命令码 3003 (0x0BBB)
|
||||
rpc RobotTaskCancel(RobotTaskCancelCommand.Request) returns (RobotTaskCancelCommand.Feedback);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user