/**
 * Copyright(C) 2020 Rokae Technology Co., Ltd.
 * All Rights Reserved.
 *
 * Information in this file is the intellectual property of Rokae Technology Co., Ltd,
 * And may contains trade secrets that must be stored and viewed confidentially.
 *
 * @date  2020-10-10
 * @brief 控制机器人的API，使用标准C接口风格
 */
#ifndef _ROBOTAPI_H_
#define _ROBOTAPI_H_

#if (defined(_WIN32) || defined(_WIN64))
#ifdef ROBOTAPI_EXPORTS
#define ROBOTAPI __declspec(dllexport)
#else
#define ROBOTAPI __declspec(dllimport)
#endif
#else
#define ROBOTAPI 
#endif

#ifdef __cplusplus
extern "C"
{
#endif

//返回码
typedef enum rokae_ret
{
    RR_SUCCESS         = 0x0000,    //执行成功
    RR_FAILED          = 0x0001,    //执行失败
    RR_TIMEOUT         = 0x0002,    //执行超时
    RR_INVALID         = 0xffff     //无效值
} rokae_rett;

//运动必须参数
#pragma pack(push, 1)
typedef struct RokaeSDKMoTionParam {
    double per;     //关节速度百分比，取值范围（1~100）
    double tcp;     //TCP线速度，取值范围（1~7000）
    double iZone;   //笛卡尔空间转弯区大小 ，取值范围（0~200）
}rokae_sdk_motion_param;
#pragma pack(pop)

//关节空间数据信息
#pragma pack(push, 1) 
typedef struct RokaeSDKGetJntRobotPosition {
    double j1;      //机器人1轴关节角度
    double j2;      //机器人2轴关节角度
    double j3;      //机器人3轴关节角度
    double j4;      //机器人4轴关节角度
    double j5;      //机器人5轴关节角度
    double j6;      //机器人6轴关节角度
}rokae_sdk_get_jnt_robot_position;
#pragma pack(pop)

//笛卡尔空间数据信息
#pragma pack(push, 1)
typedef struct RokaeSDKGetRobRobotPosition {
    double cogx;     //质心在x方向的偏移量    
    double cogy;     //质心在y方向的偏移量
    double cogz;     //质心在z方向的偏移量
    double q1;       //四元数记录负载惯量主轴的方向: q1
    double q2;       //四元数记录负载惯量主轴的方向: q2
    double q3;       //四元数记录负载惯量主轴的方向: q3
    double q4;       //四元数记录负载惯量主轴的方向: q4
    double a;        //欧拉角
    double b;        //欧拉角
    double c;        //欧拉角
}rokae_sdk_get_rob_robot_position;
#pragma pack(pop)

//通用方法
#define ROKAE_IN                    //输入参数
#define ROKAE_OUT                   //输出参数
#define ROKAE_TIMEOUT_FAST 3000     //快指令超时时长
#define ROKAE_TIMEOUT_SLOW 300000   //慢指令超时时长
#define ROKAE_IO_NAME_MAX 80        //IO名称最大长度  
/**
 * @brief rokae_last_msg 读取信息通用方法，持续保存全局操作的最后一次错误信息
 * @param str 输出信息字符串
 * @param len 输出信息字符串长度
 * @return 返回码 \enum SUCCESS：错误获取成功 \enum FAILED：错误获取失败
 */
ROBOTAPI rokae_rett rokae_last_msg(ROKAE_OUT char *str, ROKAE_OUT unsigned int *len);
/**
 * @brief rokae_exec 同步执行所有支持的指令，默认[快指令]与[慢指令]采用不同默认超时时长
 * @param cmd 命令字，目前未公开
 * @param in_data 输入内容
 * @param in_len 输入内容长度
 * @param out_data 输出内容
 * @param out_len 输出内容长度
 * @param timeout 超时时长
 * @return 标准返回码 \enum SUCCESS：执行正确 \enum FAILED：执行失败/返回失败 \enum TIMEOUT：执行超时 \enum INVALID：执行中
 */
ROBOTAPI rokae_rett rokae_exec(ROKAE_IN unsigned int cmd,
                               ROKAE_IN const char *in_data, ROKAE_IN unsigned int in_len,
                               ROKAE_OUT char *out_data, ROKAE_OUT unsigned int *out_len,
                               ROKAE_IN unsigned int timeout);

//定制方法
/**
 * @brief API_Init 初始化，完成机械手上电，建立连接等初始化操作
 * @param ip ip地址，点分十进制形式，例如："192.168.3.100"
 * @param port 端口号 0 - 65535
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_Init(ROKAE_IN const char *ip, ROKAE_IN unsigned int port);

/**
 * @brief API_Release 释放函数，执行下电，断开连接等操作
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_Release();

/**
 * @brief API_MotorOn [快指令]上电
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MotorOn();

/**
 * @brief API_MotorOff [快指令]下电
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MotorOff();

/**
 * @brief API_EmgStop [快指令]急停
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_EmgStop();

/**
 * @brief API_Stop0 [快指令]程序暂停，可以继续运行
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_Stop0();

/**
 * @brief API_Stop1 [快指令]程序停止，不可继续运行
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_Stop1();

/**
 * @brief API_PPtomain [快指令]指针指向文件头
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_PPtomain();

/**
 * @brief API_StartRun [快指令]程序运行
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_StartRun();

/**
 * @brief API_GetRobotStatus [快指令]查询机械手状态。若异常，返回异常报错信息
 * @param msg 错误信息
 * @param len 错误信息长度
 * @return 返回码 \enum SUCCESS：机器人正常 \enum FAILED：机器人错误
 */
ROBOTAPI rokae_rett API_GetRobotStatus(ROKAE_OUT char* msg, ROKAE_OUT unsigned int *len);

//位置信息数据
#pragma pack(push, 1)
typedef struct RokaeSDKGetRobotPosition {
    rokae_sdk_get_jnt_robot_position jnt_pos;
    rokae_sdk_get_rob_robot_position rob_pos;
}rokae_sdk_get_robot_position;
#pragma pack(pop)
/**
 * @brief API_GetRobotPosition [快指令]查询机械手位置。若异常，返回异常报错信息
 * @param msg 各个轴角度值
 * @param len 信息长度
 * @return 返回码 \enum SUCCESS：机器人正常 \enum FAILED：机器人错误
 */
ROBOTAPI rokae_rett API_GetRobotPosition(ROKAE_OUT rokae_sdk_get_robot_position* msg, ROKAE_OUT unsigned int* len);

/**
 * @brief   API_SetAlarmStatus [快指令]设置报警和清除报警，暂时只有清除报警功能
 * @param   value 0,清除报警
 * @return  标准返回码
 */
ROBOTAPI rokae_rett API_SetAlarmStatus(ROKAE_IN int value);

/**
 * @brief   启动机械手程序
 * @param   未定，该接口描述不清，暂不实现
 * @return  int : 错误码-- 0,OK; 返回值<0，异常，具体待定义
 */
ROBOTAPI int API_StartRobotProgram();

/**
 * @brief   停止机械手程序
 * @param   未定，该接口描述不清，暂不实现
 * @return  int : 错误码-- 0,OK; 返回值<0，异常，具体待定义
 */
ROBOTAPI int API_StopRobotProgram();

/**
 * @brief   复位机械手程序指针
 * @param   未定，该接口描述不清，暂不实现
 * @return  int : 错误码-- 0,OK; 返回值<0，异常，具体待定义
 */
ROBOTAPI int API_ResetProgramPointer();

//IO信息数据
#pragma pack(push, 1)
struct RokaeSDKIOValuePOD {
    char pod_name[ROKAE_IO_NAME_MAX];     //信号对应名字
    int pod_value;                        //信号对应电平 
};
#pragma pack(pop)
/**
 * @brief API_ReadInBit [快指令]查询DI数据。若异常，返回异常报错信息
 * @param di_name  要读取信号的名字
 * @param name_len 名字长度
 * @param msg 获取信号的信息
 * @param len 获取信息的长度
 * @return 返回码 \enum SUCCESS：机器人正常 \enum FAILED：机器人错误
 */
ROBOTAPI rokae_rett API_ReadInBit(ROKAE_IN char* di_name, ROKAE_IN int name_len, ROKAE_OUT RokaeSDKIOValuePOD* msg, ROKAE_OUT unsigned int* len);

/**
 * @brief API_WriteOutBit [快指令]设置DO数据。若异常，返回异常报错信息
 * @param msg 设置DO信息
 * @return 返回码 \enum SUCCESS：机器人正常 \enum FAILED：机器人错误
 */
ROBOTAPI rokae_rett API_WriteOutBit(ROKAE_IN RokaeSDKIOValuePOD msg);

/**
 * @brief API_UpdateToolMsg [快指令]将当前工具坐标系更新
 * @param tool_name 要切换的工具坐标名称 
 * @param name_len  要切换的工具坐标名称的长度
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_UpdateToolMsg(ROKAE_IN char* tool_name , ROKAE_IN int name_len);

/**
 * @brief   机械手返回初始位置，该初始位置预留在机械手内。
 * @return  标准返回码
 */
ROBOTAPI rokae_rett API_HomeMove();

#pragma pack(push, 1)
//MoveL，MoveJ执行时需要数据
typedef struct RokaeRobtargetPos{
    int euler_type;   //读取欧拉jog顺规类型 : 0为使用欧拉角XYZ顺规；1为使用欧拉角ZYX顺规；其他为使用四元数规则。（通常为xyz规则或四元数规则）
    rokae_sdk_motion_param  motion_param;      //运动参数
    rokae_sdk_get_rob_robot_position rob_pos;  //robtarget信息
} rokae_robtarget_pos;
#pragma pack(pop)
/**
 * @brief API_MoveLMutiPosition [慢指令]以坐标绝对位移或相对位移
 * @param iMoveMode 运动模式。0：MoveJ ； 1：MoveL;
 * @param rokae_robtarget_pos 执行MoveL,MoveJ时的必须参数
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MoveLMutiPosition(ROKAE_IN int iMoveMode, ROKAE_IN rokae_robtarget_pos *rob_pos, ROKAE_IN int num);

/**
 * @brief API_MoveLSingalPosition [慢指令]以坐标绝对位移或相对位移
 * @param iMoveMode 运动模式。0：MoveL ； 1：MoveJ;
 * @param rokae_robtarget_pos 执行MoveL,MoveJ时的必须参数
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MoveLSinglePosition(ROKAE_IN int iMoveMode, ROKAE_IN rokae_robtarget_pos rob_pos);

#pragma pack(push, 1)
//MoveL，MoveJ执行时需要数据
typedef struct RokaeRobtargetPosOff {
    rokae_robtarget_pos base_rob_pos;  //基于坐标点信息
    double x_off;     //基于base_rob_pos在x方向的偏移量    
    double y_off;     //基于base_rob_pos在y方向的偏移量
    double z_off;     //基于base_rob_pos在z方向的偏移量
} rokae_robtarget_pos_off;
#pragma pack(pop)
/**
 * @brief API_MoveLOffMutiPosition [慢指令]以坐标绝对位移或相对位移
 * @param iMoveMode 运动模式。0：MoveJOff ； 1：MoveLOff;
 * @param rokae_robtarget_pos 执行MoveL,MoveJ时的必须参数
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MoveLOffMutiPosition(ROKAE_IN int iMoveMode, ROKAE_IN rokae_robtarget_pos_off* rob_pos, ROKAE_IN int num);

/**
 * @brief API_MoveLOffSinglePosition [慢指令]以坐标绝对位移或相对位移
 * @param iMoveMode 运动模式。0：MoveJ ； 1：MoveL;
 * @param rokae_robtarget_pos 执行MoveL,MoveJ时的必须参数
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MoveLOffSinglePosition(ROKAE_IN int iMoveMode, ROKAE_IN rokae_robtarget_pos_off rob_pos);

#pragma pack(push, 1)
//MoveAbsj执行时需要数据
typedef struct RokaeJntTargetPos{
    rokae_sdk_motion_param  motion_param;      //运动参数
    rokae_sdk_get_jnt_robot_position jnt_pos;  //点位信息
} rokae_jnttarget_pos;
#pragma pack(pop)
/**
 * @brief API_MoveAbsjMutiPosition [慢指令]移动多个jntpos，对应moveabsj指令
 * @param rokae_jnttarget_pos 执行MoveAbsj时的必须参数
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MoveAbsjMutiPosition( ROKAE_IN rokae_jnttarget_pos *jnt_pos, ROKAE_IN int num);

/**
 * @brief API_MoveAbsjSinglePosition [慢指令]移动多个jntpos，对应moveabsj指令
 * @param rokae_jnttarget_pos 执行MoveAbsj时的必须参数
 * @return 标准返回码
 */
ROBOTAPI rokae_rett API_MoveAbsjSinglePosition(ROKAE_IN rokae_jnttarget_pos jnt_pos);



#ifdef __cplusplus
}
#endif 

#endif //_ROBOTAPI_H_
