/**
* @file sparse_mapping_interface.h
* @brief sparse mapping interface
*/
#ifndef _SPARSE_MAPPING_INTERFACE_H
#define _SPARSE_MAPPING_INTERFACE_H
// keyword: SPAMAP
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include "mcamera_interface.h"
#include "mdewarper_interface.h"
#include <stddef.h>
#include <stdbool.h>
/**
* @brief return value of the mapper
*
*/
typedef enum _SparseMappingResult {
SPAMAP_OK = 0,
SPAMAP_ERR_ALLOC = 1, /**< Error allocate */
SPAMAP_ERR_NON_CREATED, /**< Error create */
SPAMAP_ERR_NULL_PARAM = 3, /**< Error parameters */
SPAMAP_ERR_DONOT_SUPPORTED, /**< Do not support */
SPAMAP_ERR_UNSUPPROT_CMD, /**< Un support CMD */
SPAMAP_ERR_CAMEAR_NUM = 6, /**< Error camera number */
SPAMAP_ERR_CAMEAR_IMG_IS_NULL, /**< Image is null */
SPAMAP_ERR_STITCH_IMG_IS_NULL, /**< Stitch image is null */
SPAMAP_ERR_PARAM_INOUT_BUFF_TOOSMALL, /**< Param in/out buffer is too small */
SPAMAP_ERR_REJECTED, /**< Rejected */
SPAMAP_ERR_NO_MAP_INFO_FOUND, /**< No map info */
SPAMAP_ERR_INTERNAL, /**< Internal error */
SPAMAP_ERR_UNKNOWN
} SparseMappingResult;
/**
* @brief the status of the mapper
*
*/
typedef enum _SparseMapping_MappingState {
SPAMAP_STATE_UNKNOWN, /**< unknow state */
SPAMAP_STATE_INITED, /**< mapper is created/initialized properly, you might start to feed data */
SPAMAP_STATE_ODO_INITING, /**< visual odometry is initializing, you might continue to feed data */
SPAMAP_STATE_WORKING, /**< sparse mapping is working properly */
SPAMAP_STATE_LOST, /**< the visual odometry is lost, task failed */
SPAMAP_STATE_STOPPING, /**< mapper is stopping with some post-processing */
SPAMAP_STATE_IDLE, /**< mapper finished all the works */
SPAMAP_STATE_ERROR, /**< general error, which is not expected to occur */
SPAMAP_STATE_SUCCESS, /**< Mapping finished successfully */
SPAMAP_STATE_UNVERIFIED, /**< Mapping quality is not verified */
SPAMAP_STATE_FAILED, /**< Mapping finished but the map is bad */
SPAMAP_STATE_TERMINATED, /**< Mapping is terminated by user */
SPAMAP_STATE_NUM
} SparseMapping_MappingState;
static const char* SparseMapping_MappingStateInfo[] = {
"UNKNOWN", "INITED", "ODO_INITING", "WORKING", "LOST", "STOPPING", "IDLE", "ERROR", "SUCCESS", "UNVERIFIED", "FAILED", "TERMINATED"
};
/**
* @brief the data push option of the mapper
*
*/
typedef enum _SparseMapping_DataPushOption {
SPAMAP_PUSH_NOTHING = 0x0001,
SPAMAP_PUSH_MAPPING_STATE = SPAMAP_PUSH_NOTHING << 1, /** push SparseMapping_MappingState in data package */
SPAMAP_PUSH_TRAJECTORY = SPAMAP_PUSH_NOTHING << 2, /** push SparseMapping_DataTrajectory_t in data package */
SPAMAP_PUSH_MAP_POINTS = SPAMAP_PUSH_NOTHING << 3, /** push SparseMapping_ in data package */
} SparseMapping_DataPushOption;
typedef enum _SparseMapping_TaskType {
SPAMAP_TASK_PARK_IN,
SPAMAP_TASK_PARK_OUT,
SPAMAP_TASK_PASS_BY
} SparseMapping_TaskType;
typedef enum _SparseMapping_TrajectoryType {
SPAMAP_TRAJ_UNKNOWN,
SPAMAP_TRAJ_IN,
SPAMAP_TRAJ_OUT,
SPAMAP_TRAJ_TYPE_NUM
} SparseMapping_TrajectoryType;
/**
* @brief trajectory data
*
*/
typedef struct _SparseMapping_DataTrajectory_t {
size_t timestamp = 0; /**< timestamp of this trajectory pose */
size_t counter = 0; /**< trajectory counter for double check */
double heading = 0; /**< heading direction angle w.r.t. world x-axis, in rads*/
double qx = 0, qy = 0, qz = 0, qw = 0; /**< quarternion of the lastest trajectory pose */
double px = 0, py = 0, pz = 0; /**< position of the latest trajectory pose */
bool is_valid = false; /**< indicating if this trajectory pose is valid or not */
bool is_keyframe = false; /**< indicating if this trajectory pose is a keyframe */
SparseMapping_TrajectoryType type = SPAMAP_TRAJ_UNKNOWN; /**< indicating different trajectories before/after picking the parking lot */
} SparseMapping_DataTrajectory_t;
/**
* @brief map point
*
*/
typedef struct _SparseMapping_MapPoint_t {
double px = 0, py = 0, pz = 0; /**< 3D position of map point */
double r = 0, g = 0, b = 0; /**< color of the point, range [0, 1] */
} SparseMapping_MapPoint_t;
/**
* @brief map points
*
*/
typedef struct _SparseMapping_MapPoints_t {
int sparse_point_num = 0;
int semantic_point_num = 0;
const SparseMapping_MapPoint_t* sparse_points = nullptr;
const SparseMapping_MapPoint_t* semantic_points = nullptr;
} SparseMapping_MapPoints_t;
/**
* @brief package data
*
*/
typedef struct _SparseMapping_DataPackage_t {
SparseMapping_MappingState mapping_state;
SparseMapping_DataTrajectory_t trajectory;
SparseMapping_MapPoints_t points;
size_t counter = 0; /**< message counter for double check */
double tranversed_distance = -1.0; /**< tranversed distance, negative when invalid */
float post_processing_progress = -100.0; /**< post processing progress percentage, negative value when invalid */
} SparseMapping_DataPackage_t;
/**
* @brief CMDs for the mapper
*
*/
typedef enum _SparseMapping_CMDType {
SPAMAP_CMDType_Unknow = 0x0000,
SPAMAP_CMDType_Stop = 0x0001, /**< Finish all the post-processing task and save a final map */
SPAMAP_CMDType_Terminate = 0x0002, /**< Terminate the mapping process right away, and prepare to exit */
} SparseMapping_CMDType;
/**
* @brief camera data, we assume a grayscale image, i.e., channels = 1
*
*/
typedef struct _SparseMapping_DataCamera_t {
size_t timestamp, original_timestamp;
int sensor_id; /** correspond to camera ID */
unsigned char* buffer; /**< the actual camera buffer */
int width, height, channels; /**< as is */
} SparseMapping_DataCamera_t;
/**
* @brief Dectected 2D rectangle containing a car object
*
*/
typedef struct SparseMapping_DataCarDetectionRect_t {
float confidence; /**< confidence valude */
int px, py; /**< position of the top-left corner of the rectangle */
int w, h; /**< width and height of the rectangle */
} SparseMapping_DataCarDetectionRect_t;
typedef struct _SparseMapping_DataCarDetection_t {
size_t timestamp, original_timestamp;
int sensor_id; /** correspond to camera ID */
int rect_num; /**< number of detected rectangles */
SparseMapping_DataCarDetectionRect_t* rects; /**< Data of detected rectangles */
} SparseMapping_DataCarDetection_t;
/**
* @brief wheel data
*
*/
typedef struct _SparseMapping_DataWheel_t {
size_t timestamp, original_timestamp;
int sensor_id; /**< typically 0 */
int fl, fr, rl, rr; /**< front-left, front-right, rear-left, rear-right, in pulses */
} SparseMapping_DataWheel_t;
/**
* @brief GPS data, currently not supported
*
*/
typedef struct _SparseMapping_DataGPS_t {
size_t timestamp, original_timestamp;
int sensor_id; /**< typically 0 */
} SparseMapping_DataGPS_t;
/**
* @brief IMU data, currently not supported
*
*/
typedef struct _SparseMapping_DataIMU_t {
size_t timestamp, original_timestamp;
int sensor_id; /**< typically 0 */
double gyro_x, gyro_y, gyro_z, acc_x, acc_y, acc_z; /** the 6-axis data of IMU */
} SparseMapping_DataIMU_t;
/// -- all the macros for buffer size defined here
#define SPAMAP_CAMERA_BUFFER_NUM_MAX (4)
#define SPAMAP_STITCHSEGMENT_BUFFER_NUM_MAX (1)
#define SPAMAP_IMU_BUFFER_NUM_MAX (500)
#define SPAMAP_WHEEL_BUFFER_NUM_MAX (500)
#define SPAMAP_GPS_BUFFER_NUM_MAX (10)
/**
* @brief all the input data needed by sparse mapper
*
* @note p_wheel_data/p_gps_data/p_imu_data should be all the data between last and current camera buffer
* @note p_camera_data should be fed into sparse mapper at 10Hz or more
* @note p_stitch_segment_data is the segmented binary image of stitch image
* @note p_wheel_data should be fed into sparse mapper at 50Hz or more
* @note p_imu_data should be fed into sparse mapper at 50Hz or more
*/
typedef struct _SparseMapping_InputData_t {
int camera_data_num; /**< valid buffer size in camera_data */
SparseMapping_DataCamera_t camera_data[SPAMAP_CAMERA_BUFFER_NUM_MAX];
SparseMapping_DataCarDetection_t detection_data[SPAMAP_CAMERA_BUFFER_NUM_MAX];
int stitch_segment_image_num; /**< valid buffer size in stitch_segment_data */
SparseMapping_DataCamera_t stitch_segment_data[SPAMAP_STITCHSEGMENT_BUFFER_NUM_MAX];
int wheel_data_num; /**< valid buffer size in wheel_data */
SparseMapping_DataWheel_t wheel_data[SPAMAP_WHEEL_BUFFER_NUM_MAX];
int gps_data_num; /**< valid buffer size in gps_data */
SparseMapping_DataGPS_t gps_data[SPAMAP_GPS_BUFFER_NUM_MAX];
int imu_data_num; /**< valid buffer size in imu_data */
SparseMapping_DataIMU_t imu_data[SPAMAP_IMU_BUFFER_NUM_MAX];
} SparseMapping_InputData_t;
typedef enum _SparseMapping_POIType {
SPAMAP_POIType_DROP_OFF = 0,
SPAMAP_POIType_PICK_UP,
SPAMAP_POIType_Num,
} SparseMapping_POIType;
#define SPAMAP_TRAJECTORY_MAP_BUFFER_NUM_MAX (2000)
#define SPAMAP_CARPORTS_MAP_BUFFER_NUM_MAX (50)
#define SPAMAP_MAP_NAME_MAX (1024)
/**
* @brief the map information
*
*/
typedef struct _SparseMapping_MapInfo_t {
SparseMapping_TaskType task_type;
int trajectory_num;
SparseMapping_DataTrajectory_t trajectories[SPAMAP_TRAJECTORY_MAP_BUFFER_NUM_MAX];
char map_name[SPAMAP_MAP_NAME_MAX];
int carports_num;
SparseMapping_DataTrajectory_t carports[SPAMAP_CARPORTS_MAP_BUFFER_NUM_MAX * 4]; /**< carports under the map coordinate system */
SparseMapping_DataTrajectory_t poi_point[SPAMAP_POIType_Num];
SparseMapping_MappingState final_state; /**< final state when this map is generated */
} SparseMapping_MapInfo_t;
/**
* @brief the data requirments of mapper
*
*/
typedef struct _SparseMapping_Config_t {
bool require_stitch_segment_image, require_imu, require_wheel, require_gps; /**< user migh query these flags to feed data to mapper */
int camera_nbr; /**< number of cameras needed in total */
} SparseMapping_Config_t;
/**
* @brief handle property
*
*/
typedef struct _SparseMapping_Handle_Property_t {
bool do_stitch_segment_image; /**< perform semantic mapping or not */
bool do_verify_map;
int segment_width, segment_height; /**< resolution of stitch segment image */
const char* param_files_path;
const char* map_save_path, *map_name_prefix;
SparseMapping_TaskType task_type;
} SparseMapping_Handle_Property_t;
/**
* @brief frame info
*
*/
typedef struct _SparseMapping_Frame_Info_t {
size_t timestamp; /**< frame timestamp */
bool frame_used; /**< if this frame is actually used */
bool is_keyframe; /**< if this frame is a keyframe */
} SparseMapping_Frame_Info_t;
/**
* @brief the mapper handle
*
*/
typedef void* SparseMapping_Handle_t;
/**
* @brief Callback function type for auto-push scheme
*
* @param _udata a pointer to the user-defined data structure, while
* @param _data_package a pointer to a SparseMapping_DataPackage_t type
*/
typedef void (*SparseMapping_PushDataCallback)(void* _udata, void* _data_package);
/**
* @brief Callback function type for frame information auto-push scheme
*
* @param _udata a pointer to the user-defined data structure, while
* @param _frame_info a pointer to a SparseMapping_Frame_Info_t type
*/
typedef void (*SparseMapping_FrameInfoCallback)(void* _udata, void* _frame_info);
/**
* @brief Tags for CLA filter
*/
typedef enum _SparseMapping_CLAFilterTag {
SPAMAP_CLATAG_EGO_INIT_TIMEOUT,
SPAMAP_CLATAG_EGO_LOST,
SPAMAP_CLATAG_TOO_FEW_MAP_POINTS,
SPAMAP_CLATAG_VERIFICATION_FAILED
} SparseMapping_CLAFilterTag;
/**
* @brief Callback function type for CLA filter triggering
*
* @param _timestamp timestamp of the event
* @param _tag one of the SparseMapping_CLAFilterTag enum values
* @param _before recording milliseconds before _timestamp
* @param _after recording milliseconds after _timestamp
* @param _user_data_length length of _user_data
* @param _user_data some user data
*/
typedef void (*SparseMapping_FiltererTriggerCallback)(size_t _timestamp, int _tag, int _before, int _after, size_t _user_data_length, const unsigned char* _user_data);
/**
* @brief Pass CLA filter configurations using json string
*
* @param _handle
* @param _filterers_config_json
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_configureFilterers(SparseMapping_Handle_t _handle, const char *_filterers_config_json);
/**
* @brief Set callback function to enable auto-triggered CLA filter
*
* @param _handle
* @param _callback
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setFiltererTriggerCallback(SparseMapping_Handle_t _handle, SparseMapping_FiltererTriggerCallback _callback);
/**
* @brief print out SDK version
*
*/
void SparseMapping_printSDKVersion();
/**
* @brief Get a valid Map
*
* @param _map_path
* @param _map_info in/out
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_getValidMap(const char* _map_path, SparseMapping_MapInfo_t *_map_info);
/**
* @brief C API to create SparseMapping handle .
*
* @param _handle_property see SparseMapping_Handle_Property_t for details
* @param _error_no in/out SparseMappingResult
* @return SparseMapping_Handle_t to the created interface.
*/
SparseMapping_Handle_t SparseMapping_createHandle(const SparseMapping_Handle_Property_t* _handle_property, SparseMappingResult *_error_no);
/**
* @brief C API to get Cameras correspond to original image.
*
* @param _handle mapper handle
* @param _cameras in/out for all cameras
* @param _max_cam_num in/out camera numbers
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_getOriginCameras(SparseMapping_Handle_t _handle, mcamera::iMCamera **_cameres, size_t *_max_cam_num);
/**
* @brief C API to Update Cameras.
*
* @param _handle mapper handle
* @param _new_cameras new cameras
* @param _cam_num camera numbers
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_updateCamera(SparseMapping_Handle_t _handle, const mcamera::iMCamera **_new_cameres, const size_t _cam_num);
/**
* @brief C API to set cameras for car detection images.
*
* @param _handle mapper handle
* @param _new_cameras new cameras
* @param _cam_num camera numbers
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setCarDetectionCameras(SparseMapping_Handle_t _handle, const mcamera::iMCamera **_new_cameres, const size_t _cam_num);
/**
* @brief query the config of the mapper, you might call this function when a SparseMapping_Handle_t is created
*
* @param _handle mapper handle
* @param _config in/out the config of mapper
* @return SparseMappingResult
*
* @note this function is independent of the Sparse Mapping Interface
*/
SparseMappingResult SparseMapping_queryConfig(SparseMapping_Handle_t _handle, SparseMapping_Config_t *_config);
/**
* @brief Set callback function to enable auto-triggered result push
*
* After the callback function is properly set up, the callback function will be called
* automatically everytime when a frame is mature and out of the sliding window.
*
* @param _pushData Callback function to push data
* @param _user_data User defined data
* @param _push_option, see SparseMapping_DataPushOption
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setCallbacks(SparseMapping_Handle_t _handle, SparseMapping_PushDataCallback _call_back, void* _user_data, int _push_option);
/**
* @brief Set callback function to enable auto-triggered frame information push, used when you wanted to keep your buffer size from outside
*
* After the callback function is properly set up, the callback function will be called
* automatically everytime when a frame send to visual odometry
*
* @param _call_back Callback function to push data
* @param _user_data user defined data
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setFrameInfoCallbacks(SparseMapping_Handle_t _handle, SparseMapping_FrameInfoCallback _call_back, void* _user_data);
/**
* @brief Start the Sparse Mapping Interface Pipeline
*
* @param _handle
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_startPipeline(SparseMapping_Handle_t _handle);
/**
* @brief Stop the Sparse Mapping Interface Pipeline
*
* @param _handle the mapper handle
* @return SparseMappingResult
*
* @note this function will kill the mapper immediately, you should always feed SPAMAP_CMDType_Stop
* via SparseMapping_feedCMD to finish a normal mapping process
*/
SparseMappingResult SparseMapping_stopPipeline(SparseMapping_Handle_t _handle);
/**
* @brief Set the source buffer of all sensors needed by sparse mapper
*
* @param _handle
* @param _input_data data of the sensor buffer
* @return SparseMappingResult SPAMAP_OK when correctly executed, SPAMAP_ERR otherwise
*/
SparseMappingResult SparseMapping_feedData(SparseMapping_Handle_t _handle, const SparseMapping_InputData_t *_input_data_ptr);
/**
* @brief Set the source buffer for a specific sensor
*
* @param _handle
* @param _cmd_type Type of the CMD
* @return SparseMappingResult SPAMAP_OK when correctly executed, SPAMAP_ERR otherwise
*/
SparseMappingResult SparseMapping_feedCMD(SparseMapping_Handle_t _handle, SparseMapping_CMDType _cmd_type);
/**
* @brief set a poi point corresponds to current car position
*
* @param _handle
* @param _poi_type type of current POI(Point Of Interest)
* @return SparseMappingResult SPAMAP_OK when correctly executed, SPAMAP_ERR otherwise
*/
SparseMappingResult SparseMapping_setCurrentPOIPoint(SparseMapping_Handle_t _handle, SparseMapping_POIType _poi_type);
/**
* @brief
*
* @param _handle
* @param carports
* @return SparseMappingResult SPAMAP_OK when correctly executed, SPAMAP_ERR otherwise
*/
SparseMappingResult SparseMapping_setCurrentCarport(SparseMapping_Handle_t _handle, SparseMapping_DataTrajectory_t carports[4]);
/**
* @brief C API to destroy the previously created SparseMapping_Handle_t.
*
* @param _handle
* @return SparseMappingResult SPAMAP_OK when correctly executed, SPAMAP_ERR otherwise.
*
* @note you should call this function when mapper status is STATE_MAPPING_IDLE
*/
void SparseMapping_release(SparseMapping_Handle_t _handle);
/* ***************************************************************************** */
/**
* @brief log level
*
*/
typedef enum _SparseMapping_LogLevel {
SPAMAP_LogLevel_Debug,
SPAMAP_LogLevel_Verbose,
SPAMAP_LogLevel_Info,
SPAMAP_LogLevel_Vital,
SPAMAP_LogLevel_Warning,
SPAMAP_LogLevel_Error,
SPAMAP_LogLevel_Fatal
} SparseMapping_LogLevel;
/**
* @brief Set filename for the log (.txt), NULL by default
*
* @param _handle
* @param _log_filename
* @return SparseMappingResult SPAMAP_OK when correctly executed, SPAMAP_ERR otherwise
*/
SparseMappingResult SparseMapping_setLogFileName(SparseMapping_Handle_t _handle, const char* _log_filename);
/**
* @brief Set log level for file output, SparseMapping_LogLevelInfo by default.
*
* @param _handle
* @param _log_level One of SparseMapping_LogLevel enumerations
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setLogFileLevel(SparseMapping_Handle_t _handle, SparseMapping_LogLevel _log_level);
/**
* @brief Set log level for console output, SparseMapping_LogLevelInfo by default.
*
* @param _handle
* @param _log_level One of SparseMapping_LogLevel enumerations
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setLogConsoleLevel(SparseMapping_Handle_t _handle, SparseMapping_LogLevel _log_level);
/**
* @brief Set cpu mask for alg to bind, default is cpu core number - 1 . eg. Core number is 6, then default is 5.
*
* @param _handle
* @param _cpu_mask The mask, 0x21 : core 1 and 5
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setAlgCoreByMask(SparseMapping_Handle_t _handle, unsigned int _cpu_mask = 0x0);
/**
* @brief Enable or disable CPU utilization statistics, default is false
*
* @param _handle
* @param _enable
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setEnableCPUUtilization(SparseMapping_Handle_t _handle, bool _enable = false);
/**
* @brief Set the limit of cpu loading, lower zhen _percent, default is no limits
*
* @param _handle
* @param _percent, from 70 to 100
* @return SparseMappingResult
*/
SparseMappingResult SparseMapping_setCPULimitPercent(SparseMapping_Handle_t _handle, int _percent = 100);
const char* SparseMapping_version();
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _SPARSE_MAPPING_INTERFACE_H