|
@@ -15,93 +15,15 @@
|
|
|
#include<sys/time.h>
|
|
|
#include<sys/types.h>
|
|
|
|
|
|
-#define BYTE_CNT 88 //每次从串口中读取的字节数
|
|
|
+#define BYTE_CNT 55 //每次从串口中读取的字节数
|
|
|
#define ACCE_CONST 0.000488281 //用于计算加速度的常量16.0/32768.0
|
|
|
#define ANGULAR_CONST 0.061035156 //用于计算角速度的常量2000.0/32768.0
|
|
|
#define ANGLE_CONST 0.005493164 //用于计算欧拉角的常量180.0/32768.0
|
|
|
|
|
|
static unsigned char r_buf[BYTE_CNT]; //一次从串口中读取的数据存储缓冲区
|
|
|
-static int port_fd = -1; //串口打开时的文件描述符
|
|
|
+static int port_fd = -1; //串口打开时的文件描述符
|
|
|
static float acce[3],angular[3],angle[3],quater[4];
|
|
|
|
|
|
-/******************************************************
|
|
|
- * Description:打开IMU模块串口,输入两个参数即可连接.
|
|
|
- * open()打开失败时,返回-1,成功打开时返回文件描述符.
|
|
|
- * 各参数意义如下:
|
|
|
- * const char *path:IMU设备的挂载地址;
|
|
|
- * const int baud:串口通讯的波特率;
|
|
|
- *****************************************************/
|
|
|
-int openSerialPort(const char *path, const int baud)
|
|
|
-{
|
|
|
- int fd = 0;
|
|
|
- struct termios terminfo;
|
|
|
- bzero(&terminfo, sizeof(terminfo));
|
|
|
-
|
|
|
- fd = open(path, O_RDWR|O_NOCTTY);
|
|
|
- if (-1 == fd)
|
|
|
- {
|
|
|
- ROS_ERROR("Open 6DOF IMU dev error:%s, baud:%d", path, baud);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- //判断当前连接的设备是否为终端设备
|
|
|
- if (isatty(STDIN_FILENO) == 0)
|
|
|
- {
|
|
|
- ROS_ERROR("IMU dev isatty error !");
|
|
|
- return -2;
|
|
|
- }
|
|
|
-
|
|
|
- /*设置串口通信波特率-bps*/
|
|
|
- switch(baud)
|
|
|
- {
|
|
|
- case 9600:
|
|
|
- cfsetispeed(&terminfo, B9600); //设置输入速度
|
|
|
- cfsetospeed(&terminfo, B9600); //设置输出速度
|
|
|
- break;
|
|
|
-
|
|
|
- case 57600:
|
|
|
- cfsetispeed(&terminfo, B57600);
|
|
|
- cfsetospeed(&terminfo, B57600);
|
|
|
- break;
|
|
|
-
|
|
|
- case 115200:
|
|
|
- cfsetispeed(&terminfo, B115200);
|
|
|
- cfsetospeed(&terminfo, B115200);
|
|
|
- break;
|
|
|
-
|
|
|
- default: //设置默认波特率9600
|
|
|
- cfsetispeed(&terminfo, B9600);
|
|
|
- cfsetospeed(&terminfo, B9600);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- //设置数据位 - 8 bit
|
|
|
- terminfo.c_cflag |= CLOCAL|CREAD;
|
|
|
- terminfo.c_cflag &= ~CSIZE;
|
|
|
- terminfo.c_cflag |= CS8;
|
|
|
-
|
|
|
- //不设置奇偶校验位 - N
|
|
|
- terminfo.c_cflag &= ~PARENB;
|
|
|
-
|
|
|
- //设置停止位 - 1
|
|
|
- terminfo.c_cflag &= ~CSTOPB;
|
|
|
-
|
|
|
- //设置等待时间和最小接收字符
|
|
|
- terminfo.c_cc[VTIME] = 0;
|
|
|
- terminfo.c_cc[VMIN] = 1;
|
|
|
-
|
|
|
- //清除串口缓存的数据
|
|
|
- tcflush(fd, TCIFLUSH);
|
|
|
-
|
|
|
- if((tcsetattr(fd, TCSANOW, &terminfo)) != 0)
|
|
|
- {
|
|
|
- ROS_ERROR("set imu serial port attr error !");
|
|
|
- return -3;
|
|
|
- }
|
|
|
-
|
|
|
- return fd;
|
|
|
-}
|
|
|
-
|
|
|
/**************************************
|
|
|
* Description:关闭串口文件描述符.
|
|
|
*************************************/
|
|
@@ -112,24 +34,48 @@ int closeSerialPort(void)
|
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
|
- * Description:向IMU模块的串口中发送数据,第一步就是先解锁,其次才能
|
|
|
- * 发送控制命令,最后就是需要发送命令保存刚才的操作.解锁命令是固
|
|
|
- * 定的0xFF 0xAA 0x69 0x88 0xB5,保存命令也是固定的0xFF 0xAA 0x00
|
|
|
- * 0x00 0x00.
|
|
|
- *****************************************************************/
|
|
|
-int send_data(int fd, unsigned char *send_buffer, int length)
|
|
|
+ * Description:向IMU模块发送解锁命令,发送完命令需要延迟250ms.
|
|
|
+ ****************************************************************/
|
|
|
+static int send_unlockCmd(int fd)
|
|
|
{
|
|
|
int ret = -1;
|
|
|
unsigned char unLockCmd[5] = {0xFF, 0xAA, 0x69, 0x88, 0xB5};
|
|
|
- unsigned char saveCmd[5] = {0xFF, 0xAA, 0x00, 0x00, 0x00};
|
|
|
-
|
|
|
ret = write(fd, unLockCmd, sizeof(unLockCmd));
|
|
|
if(ret != sizeof(unLockCmd))
|
|
|
{
|
|
|
ROS_ERROR("Send IMU module unlock cmd error !");
|
|
|
return -1;
|
|
|
}
|
|
|
- ros::Duration(0.01).sleep(); //delay 10ms才能发送其他配置命令
|
|
|
+ ros::Duration(0.25).sleep(); //delay 250ms才能发送其他配置命令
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*****************************************************************
|
|
|
+ * Description:向IMU模块发送保存命令,发送完命令需要延迟250ms.
|
|
|
+ *****************************************************************/
|
|
|
+static int send_saveCmd(int fd)
|
|
|
+{
|
|
|
+ int ret = -1;
|
|
|
+ unsigned char saveCmd[5] = {0xFF, 0xAA, 0x00, 0x00, 0x00};
|
|
|
+ ret = write(fd, saveCmd, sizeof(saveCmd));
|
|
|
+ if(ret != sizeof(saveCmd))
|
|
|
+ {
|
|
|
+ ROS_ERROR("Send IMU module save cmd error !");
|
|
|
+ return -3;
|
|
|
+ }
|
|
|
+ ros::Duration(0.25).sleep(); //delay 250ms才能发送其他配置命令
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*****************************************************************
|
|
|
+ * Description:向IMU模块的串口中发送数据,第一步就是先解锁,其次才能
|
|
|
+ * 发送控制命令,最后就是需要发送两遍解锁命令、保存命令的操作.
|
|
|
+ *****************************************************************/
|
|
|
+static int send_data(int fd, unsigned char *send_buffer, int length)
|
|
|
+{
|
|
|
+ int ret = -1;
|
|
|
|
|
|
#if 0 //打印发送给IMU模块的数据,用于调试
|
|
|
printf("Send %d byte to IMU:", length);
|
|
@@ -139,34 +85,33 @@ int send_data(int fd, unsigned char *send_buffer, int length)
|
|
|
}
|
|
|
printf("\n");
|
|
|
#endif
|
|
|
+ send_unlockCmd(fd);//发送解锁命令
|
|
|
|
|
|
- //发送控制命令
|
|
|
+ //发送控制命令,需要延时250ms
|
|
|
ret = write(fd, send_buffer, length*sizeof(unsigned char));
|
|
|
if(ret != length)
|
|
|
{
|
|
|
ROS_ERROR("Send IMU module control cmd error !");
|
|
|
return -2;
|
|
|
}
|
|
|
+ ros::Duration(0.25).sleep(); //delay 250ms才能发送其他配置命令
|
|
|
|
|
|
- //发送保存命令
|
|
|
- ret = write(fd, saveCmd, sizeof(saveCmd));
|
|
|
- if(ret != sizeof(saveCmd))
|
|
|
- {
|
|
|
- ROS_ERROR("Send IMU module save cmd error !");
|
|
|
- return -3;
|
|
|
- }
|
|
|
- ros::Duration(0.1).sleep(); //delay 100ms才能进行其他操作
|
|
|
+ //发送两遍解锁保存命令
|
|
|
+ send_unlockCmd(fd); //发送解锁命令
|
|
|
+ send_saveCmd(fd); //发送保存命令
|
|
|
+ send_unlockCmd(fd); //发送解锁命令
|
|
|
+ send_saveCmd(fd); //发送保存命令
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/**************************************************************
|
|
|
* Description:根据串口数据协议来解析有效数据,这里共有4种数据.
|
|
|
- * 解析读取其中的44个字节,正好是4帧数据,每一帧数据是11个字节.
|
|
|
+ * 解析读取其中的44个字节,正好是4帧数据,每一帧数据都是11个字节.
|
|
|
* 有效数据包括加速度输出(0x55 0x51),角速度输出(0x55 0x52)
|
|
|
* 角度输出(0x55 0x53),四元素输出(0x55 0x59).
|
|
|
*************************************************************/
|
|
|
-void parse_serialData(unsigned char chr)
|
|
|
+static void parse_serialData(unsigned char chr)
|
|
|
{
|
|
|
static unsigned char chrBuf[BYTE_CNT];
|
|
|
static unsigned char chrCnt = 0; //记录读取的第几个字节
|
|
@@ -249,50 +194,43 @@ int makeYawZero(void)
|
|
|
ROS_ERROR("Send yaw zero control cmd error !");
|
|
|
return -1;
|
|
|
}
|
|
|
- ROS_INFO("set yaw to zero radian successfully !");
|
|
|
+ ROS_WARN("Set yaw to zero radian successfully !");
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/******************************************************************
|
|
|
- * Description:更新串口通信波特率,根据输入参数的不同,修改为不同的
|
|
|
- * 波特率,1修改为9600,2修改为57600,3修改为115200.修改波特率就是
|
|
|
- * 发送3条指令,第一条命令是解除锁定,然后是发送串口波特率更新命令,
|
|
|
- * 最后是保存操作的指令.
|
|
|
- ******************************************************************/
|
|
|
-int setIMUBaudRate(const int flag)
|
|
|
+ * Description:更新IMU模块的IIC地址,这里通过发送串口命令方式来更新IIC地址,
|
|
|
+ * 完整的控制命令为:0xFF 0xAA 0x1A 0x** 0x00,更新的IIC地址为第4个字节.
|
|
|
+ *****************************************************************/
|
|
|
+int updateIICAddr(std::string input)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
- int baud = 0;
|
|
|
- unsigned char baudRate[5] = {0xFF, 0xAA, 0x04, 0x00, 0x00};
|
|
|
-
|
|
|
- switch(flag)
|
|
|
+ std::stringstream num;
|
|
|
+ int addr = 0;
|
|
|
+ const char *iicAddr = NULL;
|
|
|
+ unsigned char updateIICAddrCmd[5] = {0xFF, 0xAA, 0x1A, 0x00, 0x00};
|
|
|
+
|
|
|
+ iicAddr = input.c_str();
|
|
|
+ num<<std::hex<<iicAddr+2<<std::endl;
|
|
|
+ num>>addr;
|
|
|
+ updateIICAddrCmd[3] = addr;
|
|
|
+
|
|
|
+ #if 0
|
|
|
+ for (int i=0; i<5; i++)
|
|
|
{
|
|
|
- case 1: //set baud 9600 bps
|
|
|
- baudRate[3] = 0x02;
|
|
|
- baud = 9600;
|
|
|
- break;
|
|
|
- case 2: //set baud 57600 bps
|
|
|
- baudRate[3] = 0x05;
|
|
|
- baud = 57600;
|
|
|
- break;
|
|
|
- case 3: //set baud 115200 bps
|
|
|
- baudRate[3] = 0x06;
|
|
|
- baud = 115200;
|
|
|
- break;
|
|
|
- default: //default set baud 57600 bps
|
|
|
- baudRate[3] = 0x05;
|
|
|
- baud = 57600;
|
|
|
- break;
|
|
|
+ printf("0x%02x ", updateIICAddrCmd[i]);
|
|
|
}
|
|
|
- ret = send_data(port_fd, baudRate, sizeof(baudRate));
|
|
|
+ printf("\n\n");
|
|
|
+ #endif
|
|
|
+
|
|
|
+ ret = send_data(port_fd, updateIICAddrCmd, sizeof(updateIICAddrCmd));
|
|
|
if(ret != 0)
|
|
|
{
|
|
|
- ROS_ERROR("Send baud rate update cmd error !");
|
|
|
+ ROS_ERROR("Update IMU Module IIC Address Error !");
|
|
|
return -1;
|
|
|
}
|
|
|
- ROS_INFO("Set imu new baud rate:[ %d bps] successfully !", baud);
|
|
|
- ROS_INFO("Please reconnect IMU module with new baud !");
|
|
|
+ ROS_WARN("Update IMU Module IIC Address [%s] successfully !", input.c_str());
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -301,17 +239,54 @@ int setIMUBaudRate(const int flag)
|
|
|
* Description:根据串口配置信息来连接IMU串口,准备进行数据通信,
|
|
|
* 两个输入参数的意义如下:
|
|
|
* const char* path:IMU设备的挂载地址;
|
|
|
- * const int baud:IMU模块的串口通信波特率;
|
|
|
****************************************************************/
|
|
|
-int initSerialPort(const char* path, const int baud)
|
|
|
+int initSerialPort(const char* path)
|
|
|
{
|
|
|
- port_fd = openSerialPort(path, baud);
|
|
|
- if(port_fd < 0) //打开IMU模块串口失败
|
|
|
+ struct termios terminfo;
|
|
|
+ bzero(&terminfo, sizeof(terminfo));
|
|
|
+
|
|
|
+ port_fd = open(path, O_RDWR|O_NOCTTY);
|
|
|
+ if (-1 == port_fd)
|
|
|
{
|
|
|
- ROS_ERROR("Open 6DOF IMU Module Serial Port error !");
|
|
|
+ ROS_ERROR("Open 6DOF IMU dev error:%s", path);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ //判断当前连接的设备是否为终端设备
|
|
|
+ if (isatty(STDIN_FILENO) == 0)
|
|
|
+ {
|
|
|
+ ROS_ERROR("IMU dev isatty error !");
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*设置串口通信波特率-115200bps*/
|
|
|
+ cfsetispeed(&terminfo, B115200);
|
|
|
+ cfsetospeed(&terminfo, B115200);
|
|
|
+
|
|
|
+ //设置数据位 - 8 bit
|
|
|
+ terminfo.c_cflag |= CLOCAL|CREAD;
|
|
|
+ terminfo.c_cflag &= ~CSIZE;
|
|
|
+ terminfo.c_cflag |= CS8;
|
|
|
+
|
|
|
+ //不设置奇偶校验位 - N
|
|
|
+ terminfo.c_cflag &= ~PARENB;
|
|
|
+
|
|
|
+ //设置停止位 - 1
|
|
|
+ terminfo.c_cflag &= ~CSTOPB;
|
|
|
+
|
|
|
+ //设置等待时间和最小接收字符
|
|
|
+ terminfo.c_cc[VTIME] = 0;
|
|
|
+ terminfo.c_cc[VMIN] = 1;
|
|
|
+
|
|
|
+ //清除串口缓存的数据
|
|
|
+ tcflush(port_fd, TCIFLUSH);
|
|
|
+
|
|
|
+ if((tcsetattr(port_fd, TCSANOW, &terminfo)) != 0)
|
|
|
+ {
|
|
|
+ ROS_ERROR("set imu serial port attr error !");
|
|
|
+ return -3;
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -376,7 +351,7 @@ int getImuData(void)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- //printf("recv data len:%d\n", data_len); //一次性从串口中读取的总数据字节数
|
|
|
+ //printf("recv data:%d byte\n", data_len); //一次性从串口中读取的总数据字节数
|
|
|
for (int i=0; i<data_len; i++) //将读取到的数据进行解析
|
|
|
{
|
|
|
//printf("0x%02x ", r_buf[i]);
|