更新时间:2025-01-24 08:25:49下载pdf
本文详细介绍基于 tuyaos_robot_rvc_sdk
激光扫地机的实时地图与路径传输的业务流程、API 及地图坐标系说明。
对于激光扫地机,目前支持三种类型的文件:
缩略图数据及原始高清图片属于 AI 物体识别的能力,需要扫地机硬件上带有摄像头功能。开发者根据硬件条件,可在业务上选配。
TuyaOS SDK
的状态回调 ty_rvc_event_cb
,状态只有两种:开始 和 结束。aiHD_XXXX_YYYY.bin
,通过 TuyaOS SDK
传输到应用端。其中 XXXX_YYYY
是真实的物体坐标点,应用上根据真实的坐标点获取正确的原始高清图片数据,并调用发送原始高清图片数据接口,上报给 App 。/**
* @brief Structure for coordinate points
*/
typedef struct {
int x; // X value of the coordinate point
int y; // Y value of the coordinate point
} OBJECT_POINT_S;
/**
* @brief AI thumbnail data structure
*/
typedef struct {
int map_id; // Map ID
int object_num; // Number of objects
OBJECT_POINT_S* points; // Points of objects
int* object_type; // Recognized objects
int* accuracy; // Recognition accuracy, report FF if not used
} RVC_AI_OBJECT_THUMBNAILS_INFO;
RVC_AI_OBJECT_THUMBNAILS_INFO
结构体用来存放一张地图上所有物体的坐标、类型及准确率。
/**
* @brief Names of recognized objects
*/
typedef enum {
OBJECTS_TYPE_WIRE = 0, // Wire
OBJECTS_TYPE_SHOES, // Shoes
OBJECTS_TYPE_SOCKS, // Socks
OBJECTS_TYPE_TOYS, // Toys
OBJECTS_TYPE_CHAIR, // Chair
OBJECTS_TYPE_TABLE, // Table
OBJECTS_TYPE_TRASH_CAN, // Trash can
OBJECTS_TYPE_POTTED_PLANT, // Potted plant
OBJECTS_TYPE_OTHER, // Other
OBJECTS_TYPE_MAX,
} AI_OBJECTS_TYPE_E;
物体类型 TuyaOS SDK
只定义了标准的几种方式,开发者如有新增的物体类型,需要在 OBJECTS_TYPE_OTHER
之后增加,并且需要与面板端的物体类型定义对齐。
/**
* @brief Parameters for the map protocol header of the vacuum cleaner
*/
typedef struct {
unsigned short map_id; // Map ID
int status; // Map status, 0 indicates unstable, 1 indicates stable
int height; // Height of the map in pixels
int width; // Width of the map in pixels
int resolution; // Map resolution (width/length of each grid), reported as original value, unit: meters
POINT_COOR_S origin; // Machine origin X/Y coordinates, given relative to the screen coordinate system, reported as original value
POINT_COOR_S charge_point; // Charging station X/Y coordinates, given relative to the screen coordinate system, reported as original value
int charge_angle; // Orientation of the charging station
} RVC_MAP_HEAD_INFO_S;
RVC_MAP_HEAD_INFO_S
是地图数据 RVC_MAP_DATA_S
结构体中的成员,表示扫地机地图数据的头部参数。
typedef struct {
int type; //path point type
POINT_COOR_S coordinates; //Path coordinate array, given with reference to the machine coordinate system
} PATH_POINT_S;
/**
* @brief Parameters for the path protocol of the vacuum cleaner
*/
typedef struct {
unsigned short path_id; // path ID Roadmap identification for a complete sweep
int type; //0x01 full path (normal mode) ,0x02 full path (complex mode), 0x03 Navigation path
int count; // Total number of waypoints (full)
int direction; // Device Heading Angle
PATH_POINT_S*path_point; //Path coordinate array, given with reference to the machine coordinate system, the original value is reported
} RVC_PATH_INFO_S;
RVC_PATH_INFO_S
结构体是地图路径数据,请参考 地图及路径数据结构说明。
/**
* @brief Pixel Point Types
*/
typedef enum {
OBS_FREE = 0, // Background Area
OBS_IS, // Obstacle
OBS_CARPET, // Carpet Area
OBS_CLEAN, // Cleaning Area
OBS_UNKNOW, // Unknown Area
OBS_CHARGE_ST, // Charging Station
} MAP_OBS_E;
MAP_OBS_E
是地图中像素点的枚举值。
/**
* @brief Point in the corresponding coordinate system
*/
struct svc_robot_point_s {
float x; // X-axis coordinate in the corresponding coordinate system, unit: meters
float y; // Y-axis coordinate in the corresponding coordinate system, unit: meters
float z; // Z-axis coordinate in the corresponding coordinate system, unit: meters
};
/**
* @brief Polygon parameters
*/
struct room_polygon_s {
struct svc_robot_point_s* points; // Polygon points
int points_size; // Number of points
};
/**
* @brief Area polygon parameters
*/
typedef struct {
int id; // Area ID
struct room_polygon_s polygon; // Polygon
} RVC_ROOM_POLYGON_S;
RVC_ROOM_POLYGON_S
结构体用来存放多房间边界栅格坐标点信息,需要申请结构体的内存空间。注意该结构体内的 polygon
成员是个指针,需要给该指针对象赋值。
/**
* @brief map data structer
*/
typedef struct{
RVC_MAP_HEAD_INFO_S header; //Parameters for the map protocol header of the vacuum cleaner
unsigned char** map_buff; //Pixel data on the map
int room_polygons_count; //Number of Room Zones
RVC_ROOM_POLYGON_S* room_polygons_data; //Area polygon parameters
}RVC_MAP_DATA_S;
RVC_MAP_DATA_S
结构体是用来存放一张地图数据,结构体成员包含地图开头固定数据、像素点数据、房间分区数量及边界栅格坐标点数据。
用于流媒体服务初始化。只有调用了该接口,才能正常的进行实时地图及路径的传输。
/**
* @brief real time map and path treans cb
*/
typedef INT_T (*RVC_TRANS_EVENT_CB)(IN CONST int onoff);
/***********************************************************
*@Function: tuya_sdk_media_server_init
*@brief initialize media server init
*@param[in] handler The status callback for real-time data transmission,
with statuses including: start and end.
*@return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
***********************************************************/
OPERATE_RET ty_rvc_server_init(RVC_TRANS_EVENT_CB handler);
参数说明
参数 | 说明 |
---|---|
handler | 实时地图及路径传输状态,开发者可根据状态值来判断是否开始上报数据 |
将实时地图结构化数据发送给 App 端显示,详细请参照 设备角度说明。
/***********************************************************
*@function: ty_rvc_rt_map_send_v2
*@brief: Send real-time structured map data to the app
*@param[in] map_info: map data, including fixed header data, pixel data,
the number of room zones, and boundary grid coordinate point data.
*@return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
** *********************************************************/
OPERATE_RET ty_rvc_rt_map_send_v2(RVC_MAP_DATA_S* map_info)
参数说明
参数 | 说明 |
---|---|
map_info | 地图数据,具体请参考 RVC_MAP_DATA_S 结构体 |
针对以上入参,详细请参照 地图及路径数据结构说明。
当开发者需要清空 App 端显示的地图时,调用该接口上报空地图。关于空地图的格式,在 RVC_MAP_DATA_S
结构体中:
header
成员赋值 0
map_buff
成员赋值 NULL
room_polygons_data
成员赋值 NULL
room_polygons_count
成员赋值 0
将实时路径结构化数据发送给 App 端显示。
/***********************************************************
*@function: ty_rvc_rt_cleanpath_send
*@brief send realtime cleanpath data to app
*@param[in] path_info: realtime path data which is need to be upload
*@return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
***********************************************************/
OPERATE_RET ty_rvc_rt_cleanpath_send_v2(IN RVC_PATH_INFO_S* path_info);
参数说明
参数 | 说明 |
---|---|
path_infof | 实时路径数据的内容 ,详细请参照 地图及路径数据结构说明。 |
当开发者需要清空 App 端显示的路径时,调用该接口上报空路径。关于空路径的格式,在 RVC_PATH_INFO_S
结构体中,type
路径类型填普通模式,即 1
,其余都填 0
即可。
将 AI 缩略图文件数据发送给 App。 开发者根据 RVC_AI_OBJECT_THUMBNAILS_INFO
结构体的要求,将数据传给 TuyaOS SDK
即可,TuyaOS SDK
内部会对数据进行转化之后传输给 App。
/***********************************************************
*@function: ty_rvc_rt_ai_thumbnails_send
*@brief send realtime ai thumbnails to app
*@param[in] object_info:ai object thumbnails param
*@return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
***********************************************************/
OPERATE_RET ty_rvc_rt_ai_thumbnails_send(IN RVC_AI_OBJECT_THUMBNAILS_INFO* object_info);
参数说明
参数 | 说明 |
---|---|
object_info | 缩略图数据内容 |
用于注册 AI 原始高清图文件名获取回调。开发者根据 App 下发的文件名,通过 sets_handler
回调通知到业务端,业务端根据文件名获取对应的原始高清图片数据。
/**
* @brief AI 高清图片数据回调,App 下发的 AI 高清图片文件名称 `ai_name`
*/
typedef INT_T (*RVC_AI_LOAD_DATA_CB)(CHAR_T *ai_name);
/***********************************************************
*@function: ty_rvc_ai_original_init
*@brief Callback function for get aiHD name
*@param[in] sets_handler: set unpload aiHD name cb
*@return OPERATE_RET: 0 for success, other error codes indicate failure
***********************************************************/
OPERATE_RET ty_rvc_ai_original_init(RVC_AI_LOAD_DATA_CB sets_handler);
将原始高清图片数据发送给 App。开发者根据 App 下发的文件名,通过 sets_handler
回调通知到业务端,业务端根据文件名获取对应的原始高清图片数据,传回 TuyaOS SDK
发送出去。开发者只需要将 jpg
格式的原始高清图片用文件打开并读取所有数据传给 TuyaOS SDK
,TuyaOS SDK
内部会对数据进行转化之后传输给 App。
/***********************************************************
*@Function: ty_rvc_ai_original_send
*@brief send ai origina to app
*@param[in] file_type: ai origina types include jpg, png, gif, svg, bmp, ico
*@param[in] fileBuff: ai origina buff
*@param[in] fileLen: ai origina len
*@return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
***********************************************************/
OPERATE_RET ty_rvc_ai_original_send(IN CHAR_T* file_type, IN CHAR_T* fileBuff, IN INT_T fileLen);
参数说明
参数 | 说明 |
---|---|
file_type | 高清图片类型目前支持以下六种方式: jpg、png、gif、svg、bmp、ico。如需支持其他的图片类型,请找涂鸦项目经理咨询 |
fileBuff | 实时高清图片数据的内容 |
fileLen | 实时高清图片数据的长度 |
地图数据 RVC_MAP_DATA_S
由以下几类组成:
地图固定的头部数据,是由 RVC_MAP_HEAD_INFO_S
结构体成员组成。
序号 | 字段 | 数据类型 | 说明 |
---|---|---|---|
1 | map_id | UINT16_T |
|
2 | status | UINT32_T | 用于 App 控制面板 UI 交互使用:
|
3 | height | UINT32_T | 地图像素高度,如当前无地图,该参数则为 0 |
4 | width | UINT32_T | 地图像素宽度,如当前无地图,该参数则为 0 |
5 | resolution | UINT32_T | 地图分辨率(每个格子的宽长度),原始值上报,单位:厘米 |
6 | origin | UINT32_T | 机器原点 X/Y 坐标,参照屏幕坐标系给出,原始值上报,详细请参照 地图坐标系说明 |
7 | charge_point | UINT32_T | 充电桩 X/Y 坐标,参照屏幕坐标系给出,原始值上报,充电座坐标点 X 和 Y 同时等于 0 则不显示,详细请参照 地图坐标系说明 |
8 | charge_angle | UINT32_T | 当前点的设备航向角,详细请参照 设备角度说明 |
地图中所有的像素点数据,由 map_buff
成员表示,像素值可参考 MAP_OBS_E
枚举值的定义。
根据地图的像素宽和像素高,按照二维扫描的方式在其区域内的左上角 R(0,0) 填入对应的像素点枚举值。如果当前像素点是障碍物,就用 1
表示;如果当前像素点是地毯,则用 2
表示。
地图中区域外边界信息由 RVC_ROOM_POLYGON_S
成员表示,它是指房间分区的边界点坐标。
如下图边界点:
地图上报例程
int main_test(void)
{
RVC_MAP_DATA_S rvc_map_info = { 0 };
int i = 0; int j = 0;
/*地图协议头部固定字节赋值*/
rvc_map_info.header.map_id = 0; //地图 ID
rvc_map_info.header.status = 1; //0 表示地图非稳定状态,1 表示地图稳定状态
rvc_map_info.header.width = 121; //地图像素宽度
rvc_map_info.header.height = 152; //地图像素高度
rvc_map_info.header.origin.x = 564; //机器原点 X 坐标
rvc_map_info.header.origin.y = 1357; //机器原点 Y 坐标
rvc_map_info.header.resolution = 5; //分辨率
rvc_map_info.header.charge_point.x = 0; //充电桩 X 坐标
rvc_map_info.header.charge_point.y = 0; //充电桩 Y 坐标
rvc_map_info.header.charge_angle = 0; //充电桩朝向
// 调用函数分配内存
rvc_map_info.map_buff = NULL;
char strFileInfo_buff[]; //开发者提供的原始像素点数据,按照以下二维数组的方式填充
//申请一个二维数组的内存,给 temp_map_buf 使用
for (i = 0; i < rvc_map_info.header.height; i++) {
for (j = 0; j < rvc_map_info.header.width; j++) {
rvc_map_info.map_buff[i][j] = strFileInfo_buff[rvc_map_info.header.width* i + j];
}
}
char map_buf_info[]; //开发者提供房间轮廓坐标点信息
if (map_buf_info!= NULL) { //判断数据是否有效
int room_count = 2; //开发者需要提供房间分区数量
RVC_ROOM_POLYGON_S *tmp_room_polygon = NULL;
int tmp_points_size = 0;
int offset_len = 0; //数据偏移
int all_points_size = 0; //所有坐标数量
for (i = 0; i < room_count; i++) { //遍历房间轮廓信息
all_points_size += xxxx ;//开发者提供所有房间内的边界点坐标数量
}
tmp_room_polygon = (RVC_ROOM_POLYGON_S*)Malloc(room_count * sizeof(RVC_ROOM_POLYGON_S) + all_points_size * sizeof(struct svc_robot_point_s)); //需要申请结构体的内存空间;注意该结构体内的 `polygon` 成员是个指针,需要给该指针对象赋值。
rvc_map_info.room_polygons_data = tmp_room_polygon;
float tmp_origin_x = (float)map_header.origin.x /10.0f; //获取原点坐标
float tmp_origin_y = (float)map_header.origin.y /10.0f;
struct svc_robot_point_s* points_memory =(struct svc_robot_point_s*)(tmp_room_polygon + room_count); //坐标点数据指向二级指针
for ( i = 0; i < room_count; i++) { //遍历房间轮廓信息
tmp_room_polygon->id = (map_buf_info[4 + 8 * i ] << 24) | (map_buf_info[3 + 8 * i] << 16) | (map_buf_info[2 + 8 * i] << 8) | map_buf_info[1 + 8 * i];
tmp_room_polygon->polygon.points_size = (map_buf_info[8 + 8 * i] << 24) | (map_buf_info[7 + 8 * i] << 16) | (map_buf_info[6 + 8 * i] << 8) | map_buf_info[5 + 8 * i];
PR_DEBUG("room id :%d, points size :%d", tmp_room_polygon->id, tmp_room_polygon->polygon.points_size);
offset_len = 1 + 8 * room_count + tmp_points_size; //数据偏移
tmp_room_polygon->polygon.points = points_memory;
for (j = 0; j < tmp_room_polygon->polygon.points_size; j++) {
memcpy(&tmp_room_polygon->polygon.points[j].x, map_buf_info.buff + (offset_len + j * 12), sizeof(struct svc_robot_point_s));
tmp_room_polygon->polygon.points[j].x = tmp_room_polygon->polygon.points[j].x * 100 / 5 + (tmp_origin_x); //根据分辨率及原点坐标计算出坐标数据上报面板显示。
tmp_room_polygon->polygon.points[j].y = (tmp_origin_y) - (tmp_room_polygon->polygon.points[j].y * 100 / 5) ;
tmp_room_polygon->polygon.points[j].z = tmp_room_polygon->polygon.points[j].z * 100 / 5;
// PR_DEBUG("point[%d] x:%f,y:%f, z:%f", j, tmp_room_polygon->polygon.points[j].x, tmp_room_polygon->polygon.points[j].y,tmp_room_polygon->polygon.points[j].z);
}
tmp_points_size += (tmp_room_polygon->polygon.points_size * sizeof(struct svc_robot_point_s)); //累加上房间的坐标点数量
points_memory += tmp_room_polygon->polygon.points_size; //二级指针地址偏移
tmp_room_polygon++; //获取下一个房间轮廓信息
}
rvc_map_info.room_polygons_count = room_count;
int ret = ty_rvc_rt_map_send_v2(&rvc_map_info); //地图数据上报
if(rvc_map_info.room_polygons_data != NULL) {
Free(rvc_map_info.room_polygons_data);
}
}
//申请的内存在后面需要释放
return ret;
}
路径数据的格式,可参考 RVC_PATH_INFO_S
结构体。
序号 | 字段 | 数据类型 | 说明 |
---|---|---|---|
1 | path_id | UINT16_T | 一次完整清扫的路径图标识 |
2 | type | UINT32_T | 路径类型:
|
3 | direction | UINT32_T | 设备航向角,详细请参照 设备角度说明 |
4 | count | UINT32_T | 路径点总个数(全量) |
5 | path_point | PATH_POINT_S | 路径坐标数组大小是 Count * 8,可参照 机器坐标系 |
PATH_POINT_S
结构体中的 coordinates
成员是路径坐标数组,即 X 点、Y 点,每个点 [x,y] = 1 X 8 Bytes;type
成员是路径点类型。当路径类型的值 0x01
时,代表普通仅正常清扫点路径,路径点类型只有 0x00
;当路径类型为 0x02
时,代表复杂路径。
路径点类型:
0
:清扫路径点1
:转场路径点2
:回充路径点3
:拖地路径点(暂未支持)机器人进行一次新清扫任务时,以机器人从初始位置出发,边清扫边建图,形成清扫地图和清扫路径。地图逐渐扩大,路径不断累积,过程中涉及世界坐标系、机器坐标系以及 App 显示的屏幕坐标系统,其关系如下:
实际的物理坐标系,即房间的平面坐标系,机器人每次清扫时,以世界坐标系的某一个点作为起始点,而且在本次清扫中,这个起始点在世界坐标系中的位置是不变的。世界坐标系,用于参照和理解机器坐标系。
机器人以初始点为原点,参照世界坐标系,建立机器坐标系。清扫过程中,路径点均参照以该原点,得到坐标值。
App 绘图时使用,以屏幕左上角 R(0,0) 为坐标系原点。
地图数据
App 绘图时,以原点 O 作为固定,等同于世界坐标系下,机器人初始位置不变。
路径数据
路径数据是走过的位置点的集合,其坐标为 INT32 的值,当前位置点为 P(x,y),x/y 为 P 点相对于 O 点的值。
路径坐标传输值 = 路径坐标原值 * 10,以兼顾精度与效率。
区域框等数据
区域清扫框、禁区框、虚拟墙线、指哪扫哪点等坐标数据,其坐标为 INT32 的值,坐标点 M(x,y),x/y为 M 点相对于 O 点的值,基于绘制坐标系。
区域框坐标传输值 = 区域框坐标原值 * 10,以兼顾精度与效率。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈