update src1100 module

This commit is contained in:
xtkuang 2026-07-07 15:54:09 +08:00
parent 6664d181cb
commit 2fa161f1cc
13 changed files with 2488 additions and 66 deletions

View File

@ -1,6 +1,7 @@
#ifndef CMVR_ES_AGV_TYPES_H
#define CMVR_ES_AGV_TYPES_H
#include <cstdint>
#include <optional>
#include <string>
#include <unordered_map>
@ -216,6 +217,186 @@ struct AgvPathSegment {
std::string target_station;
};
/**
* @brief AGV
*
* content SRC1100 rawmap zip
*/
struct AgvMappingDataFile {
std::string name;
std::string content;
};
/**
* @brief
*/
struct AgvMappingData {
int start_index{0};
int next_index{0};
std::vector<AgvMappingDataFile> files;
};
/**
* @brief
*
* 2D3D
* AGV
*/
enum class AgvMapDimension {
Unspecified = 0,
Map2D,
Map3D,
Map2DAnd3D
};
/**
* @brief
*/
enum class AgvMapUpdateType {
Unspecified = 0,
Snapshot,
Incremental,
Reset
};
/**
* @brief
*/
enum class AgvMapObjectType {
Unspecified = 0,
Station,
Line,
Area,
QrTag,
Reflector,
BinLocation,
ExternalDevice
};
/**
* @brief
*/
struct AgvMapPoint3D {
double x{0.0};
double y{0.0};
double z{0.0};
};
/**
* @brief 使
*/
struct AgvMapObject {
std::string id;
AgvMapObjectType type{AgvMapObjectType::Unspecified};
std::vector<AgvMapPoint3D> points;
double heading{0.0};
std::unordered_map<std::string, std::string> properties;
};
/**
* @brief 2D
*
* data -1 0 100
* /data objects
*/
struct AgvUnifiedMap2D {
std::string frame_id{"map"};
double timestamp{0.0};
double resolution{0.0};
std::uint32_t width{0};
std::uint32_t height{0};
math::Pose2d origin{};
std::vector<std::int32_t> data;
std::vector<AgvMapObject> objects;
};
/**
* @brief 3D
*/
struct AgvMapPointSample3D {
double x{0.0};
double y{0.0};
double z{0.0};
float intensity{0.0F};
std::uint32_t ring{0};
double time_offset{0.0};
};
/**
* @brief 3D
*/
struct AgvMapVoxel3D {
std::int32_t x{0};
std::int32_t y{0};
std::int32_t z{0};
float probability{-1.0F};
};
/**
* @brief 3D
*/
struct AgvMapPlane3D {
AgvMapPoint3D center;
AgvMapPoint3D normal;
double d{0.0};
double radius{0.0};
};
/**
* @brief 3D
*/
struct AgvUnifiedMap3D {
std::string frame_id{"map"};
double timestamp{0.0};
double voxel_resolution{0.0};
std::vector<AgvMapPointSample3D> points;
std::vector<AgvMapVoxel3D> voxels;
std::vector<AgvMapPlane3D> planes;
std::vector<AgvMapObject> objects;
};
/**
* @brief
*/
struct AgvMapStreamOptions {
AgvMapDimension dimension{AgvMapDimension::Unspecified};
std::string map_name;
std::string resume_token;
bool snapshot{true};
bool incremental{false};
int max_chunk_bytes{0};
int wait_timeout_ms{1000};
};
/**
* @brief /
*/
struct AgvMappingOptions {
AgvMapDimension dimension{AgvMapDimension::Unspecified};
std::string map_name;
bool real_time{false};
};
/**
* @brief
*/
struct AgvUnifiedMapUpdate {
std::string map_id;
std::string session_id;
std::uint64_t sequence{0};
std::string resume_token;
AgvMapDimension dimension{AgvMapDimension::Unspecified};
AgvMapUpdateType update_type{AgvMapUpdateType::Unspecified};
std::string frame_id{"map"};
double timestamp{0.0};
bool snapshot_begin{false};
bool snapshot_end{false};
std::uint32_t chunk_index{0};
std::uint32_t chunk_count{0};
std::optional<AgvUnifiedMap2D> map_2d;
std::optional<AgvUnifiedMap3D> map_3d;
};
/**
* @brief
*

View File

@ -11,7 +11,6 @@ agv {
id: "src1100"
src1100_agv {
ip: "192.168.192.5"
enable: false
port_status: 19204
port_control: 19205
port_nav: 19206
@ -19,6 +18,28 @@ agv {
port_other: 19210
port_push: 19301
recv_timeout_ms: 1000
enable_state_push: true
state_push_interval_ms: 200
state_push_included_fields: "x"
state_push_included_fields: "y"
state_push_included_fields: "angle"
state_push_included_fields: "vx"
state_push_included_fields: "vy"
state_push_included_fields: "w"
state_push_included_fields: "battery_level"
state_push_included_fields: "battery_temp"
state_push_included_fields: "charging"
state_push_included_fields: "voltage"
state_push_included_fields: "current"
state_push_included_fields: "current_map"
state_push_included_fields: "current_station"
state_push_included_fields: "confidence"
state_push_included_fields: "emergency"
state_push_included_fields: "fatals"
state_push_included_fields: "errors"
enable_map_update: true
map_update_interval_ms: 1000
map_update_history_size: 8
}
}
}

View File

@ -59,13 +59,6 @@ device_manager {
enable: false
}
devices {
id: "agv_1"
type: DEVICE_TYPE_AGV
config_file: "devices/agv/agv.pb.txt"
enable: false
}
devices {
id: "src1100"
type: DEVICE_TYPE_AGV

View File

@ -6,6 +6,7 @@
#define CMVR_ES_ABSTRACT_AGV_H
#pragma once
#include <cstdint>
#include <string>
#include <vector>
@ -184,6 +185,54 @@ public:
return AgvResult::failure(AgvErrorCode::UnsupportedCommand, "downloadMap not implemented");
}
/**
* @brief /
*/
virtual AgvResult startMapping(const AgvMappingOptions& options = {})
{
(void)options;
return AgvResult::failure(AgvErrorCode::UnsupportedCommand, "startMapping not implemented");
}
/**
* @brief
*
* 使 gRPC 使
* getUnifiedMapUpdate()
*/
virtual AgvResult getMappingData(int start_index, AgvMappingData& data) const
{
(void)start_index;
(void)data;
return AgvResult::failure(AgvErrorCode::UnsupportedCommand, "getMappingData not implemented");
}
/**
* @brief
*
* after_sequence 0 0
*
* options.wait_timeout_ms 线
*/
virtual AgvResult getUnifiedMapUpdate(
std::uint64_t after_sequence,
const AgvMapStreamOptions& options,
AgvUnifiedMapUpdate& update) const
{
(void)after_sequence;
(void)options;
(void)update;
return AgvResult::failure(AgvErrorCode::UnsupportedCommand, "getUnifiedMapUpdate not implemented");
}
/**
* @brief /
*/
virtual AgvResult stopMapping()
{
return AgvResult::failure(AgvErrorCode::UnsupportedCommand, "stopMapping not implemented");
}
};
} // namespace cmvr::device

View File

@ -1,8 +1,13 @@
#ifndef CMVR_ES_SRC1100_AGV_H
#define CMVR_ES_SRC1100_AGV_H
#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <deque>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
#include <json/json.h>
@ -50,6 +55,13 @@ public:
AgvResult switchMap(const std::string& map_name) override;
AgvResult uploadMap(const std::string& map_name, const std::string& content) override;
AgvResult downloadMap(const std::string& map_name, std::string& content) const override;
AgvResult startMapping(const AgvMappingOptions& options = {}) override;
AgvResult getMappingData(int start_index, AgvMappingData& data) const override;
AgvResult getUnifiedMapUpdate(
std::uint64_t after_sequence,
const AgvMapStreamOptions& options,
AgvUnifiedMapUpdate& update) const override;
AgvResult stopMapping() override;
private:
struct Ports {
@ -64,6 +76,7 @@ private:
AgvResult connect_();
AgvResult disconnect_();
AgvResult connectSocket_(int& sock, int port);
AgvResult ensureOtherSocket_();
void closeSocket_(int& sock) const;
bool connected_() const;
@ -71,12 +84,55 @@ private:
std::uint16_t command,
const Json::Value& payload,
Json::Value* response) const;
AgvResult sendCommandRaw_(int sock,
std::uint16_t command,
const Json::Value& payload,
std::string* response_payload) const;
AgvResult sendCommandNoResponse_(int sock, std::uint16_t command, const Json::Value& payload) const;
AgvResult configurePush_();
void startPushThread_();
void stopPushThread_();
void pushLoop_();
AgvRuntimeState queryRuntimeState_() const;
void updateCachedRuntimeState_(const Json::Value& payload);
void startMapUpdateThread_();
void stopMapUpdateThread_();
void mapUpdateLoop_();
AgvResult refreshMapCacheOnce_(const AgvMapStreamOptions& options) const;
AgvResult parseMapFileToUpdates_(
const std::string& file_name,
const std::string& content,
const AgvMapStreamOptions& options,
std::vector<AgvUnifiedMapUpdate>& updates) const;
AgvResult parseSrc1100MapArchive_(
const std::string& file_name,
const std::string& content,
const AgvMapStreamOptions& options,
std::vector<AgvUnifiedMapUpdate>& updates) const;
AgvResult parseSrc1100Map2D_(
const std::string& file_name,
const std::string& content,
const AgvMapStreamOptions& options,
AgvUnifiedMapUpdate& update) const;
AgvResult parseSrc1100Map3D_(
const std::string& file_name,
const std::string& content,
const AgvMapStreamOptions& options,
AgvUnifiedMapUpdate& update) const;
void cacheMapUpdates_(std::vector<AgvUnifiedMapUpdate> updates) const;
bool findCachedMapUpdate_(
std::uint64_t after_sequence,
const AgvMapStreamOptions& options,
AgvUnifiedMapUpdate& update) const;
bool mapUpdateMatches_(
const AgvUnifiedMapUpdate& update,
const AgvMapStreamOptions& options) const;
static std::vector<std::uint8_t> buildFrame_(std::uint16_t command, const std::string& payload);
static std::string toJsonString_(const Json::Value& value);
static bool parseJson_(const std::string& input, Json::Value& output, std::string& error);
static std::string extractJson_(const std::string& raw);
static AgvResult receiveFrame_(int sock, std::uint16_t& command, std::string& payload);
static int optionalInt_(const AgvAdapterParams& params, const std::string& key, int fallback);
static double optionalDouble_(const AgvAdapterParams& params, const std::string& key, double fallback);
static void applyMotionOptions_(Json::Value& payload, const AgvMotionOptions& options);
@ -87,6 +143,10 @@ private:
std::string ip_;
int recv_timeout_ms_{1000};
Ports ports_;
bool state_push_enabled_{false};
bool map_update_enabled_{false};
int map_update_interval_ms_{1000};
std::size_t map_update_history_size_{8};
mutable std::mutex mutex_;
int sock_status_{-1};
@ -96,6 +156,22 @@ private:
int sock_other_{-1};
int sock_push_{-1};
std::string last_error_;
std::atomic<bool> push_running_{false};
std::thread push_thread_;
mutable std::mutex runtime_state_mutex_;
AgvRuntimeState cached_runtime_state_;
bool cached_runtime_state_valid_{false};
mutable std::atomic<bool> map_update_running_{false};
mutable std::thread map_update_thread_;
mutable std::mutex map_update_mutex_;
mutable std::condition_variable map_update_cv_;
mutable std::deque<AgvUnifiedMapUpdate> cached_map_updates_;
mutable std::uint64_t map_sequence_{0};
mutable int next_mapping_index_{0};
mutable std::size_t last_map_content_hash_{0};
mutable std::string map_session_id_;
};
} // namespace cmvr::device

File diff suppressed because it is too large Load Diff

View File

@ -63,6 +63,15 @@ public:
grpc::Status downloadMap(grpc::ServerContext* context,
const api::AgvMapCommand_Request* request,
api::AgvMapCommand_Feedback* response) override;
grpc::Status startMapping(grpc::ServerContext* context,
const api::AgvStartMappingCommand_Request* request,
api::AgvStartMappingCommand_Feedback* response) override;
grpc::Status streamMap(grpc::ServerContext* context,
const api::AgvMapStreamCommand_Request* request,
grpc::ServerWriter<api::AgvMapStreamCommand_Feedback>* writer) override;
grpc::Status stopMapping(grpc::ServerContext* context,
const api::CommandHeader_Request* request,
api::CommandHeader_Feedback* response) override;
private:
device::DeviceManager& dmgr_;

View File

@ -1,5 +1,6 @@
#include "service/grpc/include/grpc_agv_service.h"
#include <cstdint>
#include <exception>
#include <string>
#include <vector>
@ -98,6 +99,74 @@ math::Pose2d toPose2d(const msgs::AgvPose2d& src)
return {src.x(), src.y(), src.theta()};
}
device::AgvMapDimension toMapDimension(const msgs::AgvMapDimension src)
{
switch (src) {
case msgs::AGV_MAP_2D:
return device::AgvMapDimension::Map2D;
case msgs::AGV_MAP_3D:
return device::AgvMapDimension::Map3D;
case msgs::AGV_MAP_2D_AND_3D:
return device::AgvMapDimension::Map2DAnd3D;
case msgs::AGV_MAP_DIMENSION_UNSPECIFIED:
default:
return device::AgvMapDimension::Unspecified;
}
}
msgs::AgvMapDimension toProtoMapDimension(const device::AgvMapDimension src)
{
switch (src) {
case device::AgvMapDimension::Map2D:
return msgs::AGV_MAP_2D;
case device::AgvMapDimension::Map3D:
return msgs::AGV_MAP_3D;
case device::AgvMapDimension::Map2DAnd3D:
return msgs::AGV_MAP_2D_AND_3D;
case device::AgvMapDimension::Unspecified:
default:
return msgs::AGV_MAP_DIMENSION_UNSPECIFIED;
}
}
msgs::AgvMapUpdateType toProtoMapUpdateType(const device::AgvMapUpdateType src)
{
switch (src) {
case device::AgvMapUpdateType::Snapshot:
return msgs::AGV_MAP_UPDATE_SNAPSHOT;
case device::AgvMapUpdateType::Incremental:
return msgs::AGV_MAP_UPDATE_INCREMENTAL;
case device::AgvMapUpdateType::Reset:
return msgs::AGV_MAP_UPDATE_RESET;
case device::AgvMapUpdateType::Unspecified:
default:
return msgs::AGV_MAP_UPDATE_UNSPECIFIED;
}
}
msgs::AgvMapObjectType toProtoMapObjectType(const device::AgvMapObjectType src)
{
switch (src) {
case device::AgvMapObjectType::Station:
return msgs::AGV_MAP_OBJECT_STATION;
case device::AgvMapObjectType::Line:
return msgs::AGV_MAP_OBJECT_LINE;
case device::AgvMapObjectType::Area:
return msgs::AGV_MAP_OBJECT_AREA;
case device::AgvMapObjectType::QrTag:
return msgs::AGV_MAP_OBJECT_QR_TAG;
case device::AgvMapObjectType::Reflector:
return msgs::AGV_MAP_OBJECT_REFLECTOR;
case device::AgvMapObjectType::BinLocation:
return msgs::AGV_MAP_OBJECT_BIN_LOCATION;
case device::AgvMapObjectType::ExternalDevice:
return msgs::AGV_MAP_OBJECT_EXTERNAL_DEVICE;
case device::AgvMapObjectType::Unspecified:
default:
return msgs::AGV_MAP_OBJECT_UNSPECIFIED;
}
}
void fillPose2d(msgs::AgvPose2d* dst, const math::Pose2d& src)
{
dst->set_x(src.x);
@ -154,6 +223,97 @@ void fillStation(msgs::AgvStation* dst, const device::AgvStation& src)
dst->set_description(src.description);
}
void fillMapPoint3D(msgs::AgvMapPoint3D* dst, const device::AgvMapPoint3D& src)
{
dst->set_x(src.x);
dst->set_y(src.y);
dst->set_z(src.z);
}
void fillMapObject(msgs::AgvMapObject* dst, const device::AgvMapObject& src)
{
dst->set_id(src.id);
dst->set_type(toProtoMapObjectType(src.type));
for (const auto& point : src.points) {
fillMapPoint3D(dst->add_points(), point);
}
dst->set_heading(src.heading);
auto* properties = dst->mutable_properties();
for (const auto& [key, value] : src.properties) {
(*properties)[key] = value;
}
}
void fillUnifiedMap2D(msgs::AgvUnifiedMap2D* dst, const device::AgvUnifiedMap2D& src)
{
dst->set_frame_id(src.frame_id);
dst->set_timestamp(src.timestamp);
dst->set_resolution(src.resolution);
dst->set_width(src.width);
dst->set_height(src.height);
fillPose2d(dst->mutable_origin(), src.origin);
for (const auto value : src.data) {
dst->add_data(value);
}
for (const auto& object : src.objects) {
fillMapObject(dst->add_objects(), object);
}
}
void fillUnifiedMap3D(msgs::AgvUnifiedMap3D* dst, const device::AgvUnifiedMap3D& src)
{
dst->set_frame_id(src.frame_id);
dst->set_timestamp(src.timestamp);
dst->set_voxel_resolution(src.voxel_resolution);
for (const auto& point : src.points) {
auto* dst_point = dst->add_points();
dst_point->set_x(point.x);
dst_point->set_y(point.y);
dst_point->set_z(point.z);
dst_point->set_intensity(point.intensity);
dst_point->set_ring(point.ring);
dst_point->set_time_offset(point.time_offset);
}
for (const auto& voxel : src.voxels) {
auto* dst_voxel = dst->add_voxels();
dst_voxel->set_x(voxel.x);
dst_voxel->set_y(voxel.y);
dst_voxel->set_z(voxel.z);
dst_voxel->set_probability(voxel.probability);
}
for (const auto& plane : src.planes) {
auto* dst_plane = dst->add_planes();
fillMapPoint3D(dst_plane->mutable_center(), plane.center);
fillMapPoint3D(dst_plane->mutable_normal(), plane.normal);
dst_plane->set_d(plane.d);
dst_plane->set_radius(plane.radius);
}
for (const auto& object : src.objects) {
fillMapObject(dst->add_objects(), object);
}
}
void fillUnifiedMapUpdate(msgs::AgvUnifiedMapUpdate* dst, const device::AgvUnifiedMapUpdate& src)
{
dst->set_map_id(src.map_id);
dst->set_session_id(src.session_id);
dst->set_sequence(src.sequence);
dst->set_resume_token(src.resume_token);
dst->set_dimension(toProtoMapDimension(src.dimension));
dst->set_update_type(toProtoMapUpdateType(src.update_type));
dst->set_frame_id(src.frame_id);
dst->set_timestamp(src.timestamp);
dst->set_snapshot_begin(src.snapshot_begin);
dst->set_snapshot_end(src.snapshot_end);
dst->set_chunk_index(src.chunk_index);
dst->set_chunk_count(src.chunk_count);
if (src.map_2d) {
fillUnifiedMap2D(dst->mutable_map_2d(), *src.map_2d);
} else if (src.map_3d) {
fillUnifiedMap3D(dst->mutable_map_3d(), *src.map_3d);
}
}
} // namespace
gRPCAgvServiceImpl::gRPCAgvServiceImpl()
@ -478,4 +638,115 @@ grpc::Status gRPCAgvServiceImpl::downloadMap(grpc::ServerContext*,
}
}
grpc::Status gRPCAgvServiceImpl::startMapping(grpc::ServerContext*,
const api::AgvStartMappingCommand_Request* request,
api::AgvStartMappingCommand_Feedback* response)
{
try {
const std::string device_id = request->header().device_id();
auto agv = dmgr_.getDevice<device::AbstractAGV>(device_id);
if (!agv) {
return setDeviceNotFound(response, device_id);
}
device::AgvMappingOptions options;
options.dimension = toMapDimension(request->dimension());
options.map_name = request->map_name();
options.real_time = request->real_time();
const auto result = agv->startMapping(options);
if (result.ok()) {
response->set_session_id(device_id + "_mapping");
}
return setResponseResult(response, result);
} catch (const std::exception& e) {
fillFeedback(response->mutable_header(), false, e.what());
return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
}
}
grpc::Status gRPCAgvServiceImpl::streamMap(grpc::ServerContext* context,
const api::AgvMapStreamCommand_Request* request,
grpc::ServerWriter<api::AgvMapStreamCommand_Feedback>* writer)
{
try {
const std::string device_id = request->header().device_id();
auto agv = dmgr_.getDevice<device::AbstractAGV>(device_id);
api::AgvMapStreamCommand_Feedback feedback;
if (!agv) {
const std::string message = "AGV device not found: " + device_id;
fillFeedback(feedback.mutable_header(), false, message);
writer->Write(feedback);
return grpc::Status(grpc::StatusCode::NOT_FOUND, message);
}
device::AgvMapStreamOptions options;
options.dimension = toMapDimension(request->dimension());
options.map_name = request->map_name();
options.resume_token = request->resume_token();
options.snapshot = request->snapshot();
options.incremental = request->incremental();
options.max_chunk_bytes = request->max_chunk_bytes();
std::uint64_t after_sequence = 0;
if (!request->resume_token().empty()) {
try {
after_sequence = static_cast<std::uint64_t>(std::stoull(request->resume_token()));
} catch (...) {
after_sequence = 0;
}
}
bool wrote_any = false;
while (!context->IsCancelled()) {
options.wait_timeout_ms = (!options.incremental && wrote_any) ? 20 : 1000;
device::AgvUnifiedMapUpdate update;
const auto result = agv->getUnifiedMapUpdate(after_sequence, options, update);
if (!result.ok()) {
if (result.code == device::AgvErrorCode::Timeout && wrote_any && !options.incremental) {
return grpc::Status::OK;
}
if (result.code == device::AgvErrorCode::Timeout && wrote_any && options.incremental) {
continue;
}
fillFeedback(feedback.mutable_header(), false, result.message);
writer->Write(feedback);
return resultToStatus(result);
}
api::AgvMapStreamCommand_Feedback update_feedback;
fillFeedback(update_feedback.mutable_header(), true);
fillUnifiedMapUpdate(update_feedback.mutable_update(), update);
if (!writer->Write(update_feedback)) {
return grpc::Status(grpc::StatusCode::CANCELLED, "AGV map stream writer closed");
}
wrote_any = true;
after_sequence = update.sequence;
options.resume_token.clear();
}
return grpc::Status(grpc::StatusCode::CANCELLED, "AGV map stream cancelled");
} catch (const std::exception& e) {
api::AgvMapStreamCommand_Feedback feedback;
fillFeedback(feedback.mutable_header(), false, e.what());
writer->Write(feedback);
return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
}
}
grpc::Status gRPCAgvServiceImpl::stopMapping(grpc::ServerContext*,
const api::CommandHeader_Request* request,
api::CommandHeader_Feedback* response)
{
try {
auto agv = dmgr_.getDevice<device::AbstractAGV>(request->device_id());
if (!agv) {
return setDeviceNotFound(response, request->device_id());
}
return setResponseResult(response, agv->stopMapping());
} catch (const std::exception& e) {
fillFeedback(response, false, e.what());
return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
}
}
} // namespace cmvr::service

View File

@ -5,98 +5,208 @@ package cmvr.api;
import "cmvr/api/common.proto";
import "cmvr/msgs/agv.proto";
// AGV
message AgvRuntimeStateCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
// AGV
cmvr.msgs.AgvRuntimeState state = 2;
}
}
// AGV
message AgvNavigationStatusCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
//
cmvr.msgs.AgvNavigationStatus status = 2;
}
}
// 姿
message AgvNavigateToPoseCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
// 姿x/y theta
cmvr.msgs.AgvPose2d pose = 2;
//
cmvr.msgs.AgvMotionOptions options = 3;
// AGV
cmvr.msgs.AgvAdapterParams adapter_params = 4;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
}
}
//
message AgvNavigateToStationCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
// id
string station_id = 2;
//
cmvr.msgs.AgvMotionOptions options = 3;
// AGV
cmvr.msgs.AgvAdapterParams adapter_params = 4;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
}
}
//
message AgvFollowPathCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
// id id
repeated cmvr.msgs.AgvPathSegment path = 2;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
}
}
//
message AgvSetVelocityCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
// vx/vy /wz /
cmvr.msgs.AgvVelocity velocity = 2;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
}
}
//
message AgvListMapsCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
//
repeated string maps = 2;
}
}
//
message AgvListStationsCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
//
repeated cmvr.msgs.AgvStation stations = 2;
}
}
//
message AgvMapCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
// /
string map_name = 2;
// 使
string content = 3;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
//
string content = 2;
}
}
// /
message AgvStartMappingCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
// 2D3D
cmvr.msgs.AgvMapDimension dimension = 2;
// AGV /
string map_name = 3;
// true false 线/
bool real_time = 4;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
// id
string session_id = 2;
}
}
//
message AgvMapStreamCommand {
//
message Request {
// header.device_id AGV
CommandHeader.Request header = 1;
// 2D3D
cmvr.msgs.AgvMapDimension dimension = 2;
// 使/
string map_name = 3;
//
string resume_token = 4;
// true
bool snapshot = 5;
// update_type
bool incremental = 6;
// 0 使
int32 max_chunk_bytes = 7;
}
//
message Feedback {
//
CommandHeader.Feedback header = 1;
// payload map_2d map_3d
cmvr.msgs.AgvUnifiedMapUpdate update = 2;
}
}

View File

@ -5,22 +5,68 @@ package cmvr.api;
import "cmvr/api/common.proto";
import "cmvr/api/agv_command.proto";
// AGV
// AGV
service AgvService {
// AGV
rpc getRuntimeState(AgvRuntimeStateCommand.Request) returns (AgvRuntimeStateCommand.Feedback);
//
rpc getNavigationStatus(AgvNavigationStatusCommand.Request) returns (AgvNavigationStatusCommand.Feedback);
//
rpc emergencyStop(CommandHeader.Request) returns (CommandHeader.Feedback);
//
rpc clearFault(CommandHeader.Request) returns (CommandHeader.Feedback);
// 姿姿 x/y theta
rpc navigateToPose(AgvNavigateToPoseCommand.Request) returns (AgvNavigateToPoseCommand.Feedback);
//
rpc navigateToStation(AgvNavigateToStationCommand.Request) returns (AgvNavigateToStationCommand.Feedback);
//
rpc followPath(AgvFollowPathCommand.Request) returns (AgvFollowPathCommand.Feedback);
//
rpc pauseNavigation(CommandHeader.Request) returns (CommandHeader.Feedback);
//
rpc resumeNavigation(CommandHeader.Request) returns (CommandHeader.Feedback);
//
rpc cancelNavigation(CommandHeader.Request) returns (CommandHeader.Feedback);
// vx/vy /wz /
rpc setVelocity(AgvSetVelocityCommand.Request) returns (AgvSetVelocityCommand.Feedback);
//
rpc stopVelocityControl(CommandHeader.Request) returns (CommandHeader.Feedback);
// AGV
rpc listMaps(AgvListMapsCommand.Request) returns (AgvListMapsCommand.Feedback);
//
rpc listStations(AgvListStationsCommand.Request) returns (AgvListStationsCommand.Feedback);
// 使
rpc switchMap(AgvMapCommand.Request) returns (AgvMapCommand.Feedback);
// AGV
rpc uploadMap(AgvMapCommand.Request) returns (AgvMapCommand.Feedback);
//
rpc downloadMap(AgvMapCommand.Request) returns (AgvMapCommand.Feedback);
// / 2D3D
// AGV
rpc startMapping(AgvStartMappingCommand.Request) returns (AgvStartMappingCommand.Feedback);
// resume_token
// AGV update_type
rpc streamMap(AgvMapStreamCommand.Request) returns (stream AgvMapStreamCommand.Feedback);
// /
rpc stopMapping(CommandHeader.Request) returns (CommandHeader.Feedback);
}

View File

@ -1,39 +1,78 @@
syntax = "proto3";
package cmvr.config;
// / AGV
message MyAgvConfig {
// id AGVDeviceConfig.id
string id = 1;
// AGV IP
string ip = 2;
// AGV
int32 port = 3;
}
// SRC1100 AGV
message Src1100AgvConfig {
// id AGVDeviceConfig.id
string id = 1;
// SRC1100 IP
string ip = 2;
//
bool enable = 3;
// 19204
int32 port_status = 4;
// 19205
int32 port_control = 5;
// 19206
int32 port_nav = 6;
// / 19207
int32 port_config = 7;
// 19210/
int32 port_other = 8;
// 19301
int32 port_push = 9;
// 0 使
int32 connect_timeout_ms = 10;
// 0 使
int32 recv_timeout_ms = 11;
//
bool enable_state_push = 12;
// 0
int32 state_push_interval_ms = 13;
// state_push_excluded_fields
repeated string state_push_included_fields = 14;
// state_push_included_fields
repeated string state_push_excluded_fields = 15;
// 线 gRPC
bool enable_map_update = 16;
// 0 使
int32 map_update_interval_ms = 17;
// 0 使
uint32 map_update_history_size = 18;
}
// AGV
message AGVDeviceConfig {
// id AGV id
string id = 1;
// AGV
oneof backend {
// / AGV
MyAgvConfig my_agv = 10;
// SRC1100 AGV
Src1100AgvConfig src1100_agv = 11;
}
}
// AGV
message AGVConfig {
// AGV
repeated AGVDeviceConfig agvs = 1;
}
// AGV
message AGVRootConfig {
// AGV
AGVConfig agv = 1;
}

View File

@ -2,72 +2,309 @@ syntax = "proto3";
package cmvr.msgs;
// AGV 姿
message AgvPose2d {
// X
double x = 1;
// Y
double y = 2;
//
double theta = 3;
}
// AGV
message AgvVelocity {
// X 线/
double vx = 1;
// Y 线/
double vy = 2;
// Z /
double wz = 3;
}
// AGV
message AgvBatteryState {
// [0, 1] 0.8 80%
double percentage = 1;
//
double voltage = 2;
// AGV
double current = 3;
//
double temperature = 4;
//
bool charging = 5;
}
//
message AgvMotionOptions {
// 线/0 使 AGV
double max_speed = 1;
// /0 使 AGV
double max_angular_speed = 2;
// 线/^20 使 AGV
double max_acceleration = 3;
// /^20 使 AGV
double max_angular_acceleration = 4;
// 0 使 AGV
double reach_distance = 5;
// 0 使 AGV
double reach_angle = 6;
// [0, 1]1
double speed_ratio = 7;
// true
bool asynchronous = 8;
}
// AGV
message AgvAdapterParams {
// 使 AGV
map<string, string> values = 1;
}
// AGV
message AgvRuntimeState {
// Unix
double timestamp = 1;
// AgvMode
int32 mode = 2;
// AGV
bool connected = 3;
//
bool localized = 4;
// AGV
bool moving = 5;
// AGV
bool fault = 6;
// AGV
bool emergency_stopped = 7;
// 姿
AgvPose2d pose = 8;
//
AgvVelocity velocity = 9;
//
AgvBatteryState battery = 10;
//
string current_map = 11;
// id
string current_station = 12;
//
string last_error = 13;
}
//
message AgvStation {
// id
string id = 1;
//
string type = 2;
// 姿
AgvPose2d pose = 3;
//
string description = 4;
}
//
message AgvPathSegment {
// id
string source_station = 1;
// id
string target_station = 2;
}
// 2D3D
// AGV
enum AgvMapDimension {
//
AGV_MAP_DIMENSION_UNSPECIFIED = 0;
// 2D
AGV_MAP_2D = 1;
// 3D
AGV_MAP_3D = 2;
// 2D 3D
AGV_MAP_2D_AND_3D = 3;
}
//
enum AgvMapUpdateType {
//
AGV_MAP_UPDATE_UNSPECIFIED = 0;
//
AGV_MAP_UPDATE_SNAPSHOT = 1;
//
AGV_MAP_UPDATE_INCREMENTAL = 2;
//
AGV_MAP_UPDATE_RESET = 3;
}
// 2D/3D
enum AgvMapObjectType {
//
AGV_MAP_OBJECT_UNSPECIFIED = 0;
//
AGV_MAP_OBJECT_STATION = 1;
// 线线线线
AGV_MAP_OBJECT_LINE = 2;
//
AGV_MAP_OBJECT_AREA = 3;
//
AGV_MAP_OBJECT_QR_TAG = 4;
//
AGV_MAP_OBJECT_REFLECTOR = 5;
//
AGV_MAP_OBJECT_BIN_LOCATION = 6;
//
AGV_MAP_OBJECT_EXTERNAL_DEVICE = 7;
}
//
message AgvMapPoint3D {
// X
double x = 1;
// Y
double y = 2;
// Z 2D 0
double z = 3;
}
// 2D index = y * width + x
message AgvUnifiedMap2D {
// "map"
string frame_id = 1;
// Unix
double timestamp = 2;
// /
double resolution = 3;
//
uint32 width = 4;
//
uint32 height = 5;
// (0, 0) /姿x/y theta
AgvPose2d origin = 6;
// -1 0 100
repeated int32 data = 7;
// 线
repeated AgvMapObject objects = 8;
}
// 3D
message AgvMapPointSample3D {
// X
double x = 1;
// Y
double y = 2;
// Z
double z = 3;
// 0
float intensity = 4;
// 线/ 0
uint32 ring = 5;
// 0
double time_offset = 6;
}
// 3D AgvUnifiedMap3D.voxel_resolution
message AgvMapVoxel3D {
// X
int32 x = 1;
// Y
int32 y = 2;
// Z
int32 z = 3;
// [0, 1] -1
float probability = 4;
}
// 3D
// normal.x * x + normal.y * y + normal.z * z + d = 0
message AgvMapPlane3D {
//
AgvMapPoint3D center = 1;
//
AgvMapPoint3D normal = 2;
//
double d = 3;
//
double radius = 4;
}
// 使
message AgvMapObject {
// id
string id = 1;
//
AgvMapObjectType type = 2;
// 使 1 线使使
repeated AgvMapPoint3D points = 3;
// 0
double heading = 4;
// AGV使
map<string, string> properties = 5;
}
// 3D
// 3D
message AgvUnifiedMap3D {
// "map"
string frame_id = 1;
// Unix
double timestamp = 2;
// / 0
double voxel_resolution = 3;
//
repeated AgvMapPointSample3D points = 4;
//
repeated AgvMapVoxel3D voxels = 5;
//
repeated AgvMapPlane3D planes = 6;
// 3D
repeated AgvMapObject objects = 7;
}
// AGV map_2d map_3d
//
message AgvUnifiedMapUpdate {
// id map_name AGV
string map_id = 1;
// id
string session_id = 2;
// 0 1
uint64 sequence = 3;
//
string resume_token = 4;
//
AgvMapDimension dimension = 5;
//
AgvMapUpdateType update_type = 6;
// "map"
string frame_id = 7;
// Unix
double timestamp = 8;
//
bool snapshot_begin = 9;
//
bool snapshot_end = 10;
// 0
uint32 chunk_index = 11;
// 0
uint32 chunk_count = 12;
oneof payload {
// 2D 2D
AgvUnifiedMap2D map_2d = 20;
// 3D 3D
AgvUnifiedMap3D map_3d = 21;
}
}
//
message AgvNavigationStatus {
// AgvTaskState
int32 state = 1;
// AgvTaskType
int32 type = 2;
// [0, 1] 0
double progress = 3;
//
string message = 4;
}

View File

@ -0,0 +1,124 @@
syntax = "proto3";
package rbk.protocol;
// SRC1100 3D 0.3dsmap
// protobuf
//
message Message_MapPos {
// X
double x = 1;
// Y
double y = 2;
// Z
double z = 3;
}
//
message Message_MapHeader {
// 2D-Map 3D-Map
string map_type = 1;
//
string map_name = 2;
//
Message_MapPos min_pos = 3;
//
Message_MapPos max_pos = 4;
//
double resolution = 5;
//
string version = 8;
}
//
message Vec3f {
// X
float x = 1;
// Y
float y = 2;
// Z
float z = 3;
}
//
message Vec3i {
// X
int32 x = 1;
// Y
int32 y = 2;
// Z
int32 z = 3;
}
// 3D
message FeatureMapParams {
//
float ranging_sigma = 1;
//
float angle_sigma = 2;
//
float max_voxel_size = 3;
//
uint32 max_layer = 4;
//
uint32 cov_fixed_pts_num = 5;
//
uint32 plane_fixed_pts_num = 6;
//
float plane_min_eigen_value = 7;
//
repeated int32 each_layer_least_pts_num = 8;
}
// 3D
message FeatureMapPlane {
//
Vec3f center = 1;
//
Vec3f normal = 2;
// Ax + By + Cz + D = 0 D
float d = 3;
//
float radius = 4;
// 6x6
repeated float plane_cov = 5;
}
//
message OctoTree {
// ID
uint32 plane_id = 1;
// -1
repeated int32 child_id_list = 2;
}
//
message OctoTrees {
//
repeated OctoTree octo_tree = 1;
}
// 3D
message FeatureMap3D {
//
FeatureMapParams params = 1;
//
repeated FeatureMapPlane planes = 2;
//
repeated OctoTrees octo_trees = 3;
//
repeated Vec3i voxel_locs = 4;
}
// 0.3dsmap
message Message_Map3D {
//
string map_directory = 1;
//
Message_MapHeader header = 2;
// 3D
repeated Message_MapPos normal_pos3d_list = 3;
// 3D
FeatureMap3D feature_map_3d = 4;
}