一、实践过程
根据can分析仪说明文档里面的API接口函数定义,以及电机的CANopen通讯协议,使用SDO数据通信格式,编写ROS/C++程序。首先拿一个小电机在工位上调 , 然后小电机能动之后 , 再基于底盘的运动学模型 , 编写驱动差速底盘的程序:
接收**/cmd_vel话题,消息类型是twist** , 上层的算法解算出控制量线速度和角速度之后,此程序计算两边轮子的速度并换算成电机速度,通过SDO通信格式发送数据帧给底盘电机,控制底盘以给定的线速度和角速度运动。
二、CAN协议和CANopen协议
CANopen是一种基于CAN通信协议的高层通信协议。它定义了一套标准化的通信规则,确保不同制造商生产的设备能够互相通信和协同工作。
/*电机使能*/
void motor_enable(uint32_t motor_id)
{
VCI_CAN_OBJ motor_enable[1];
motor_enable[0].ID = motor_id;
motor_enable[0].SendType = 0;
motor_enable[0].RemoteFlag = 0;
motor_enable[0].ExternFlag = 0;
motor_enable[0].DataLen = 8;
motor_enable[0].Data[0] = 0x2b; // 写入
motor_enable[0].Data[1] = 0x40; // 使能索引
motor_enable[0].Data[2] = 0x60; // 使能索引
motor_enable[0].Data[3] = 0x00;
motor_enable[0].Data[4] = 0x1f; // 设定值
motor_enable[0].Data[5] = 0x00;
motor_enable[0].Data[6] = 0x00;
motor_enable[0].Data[7] = 0x00;
// uint8_t motor_enable[8]={0x2b,0x40,0x60,0x00,0x1f,0x00,0x00,0x00};
VCI_Transmit(VCI_USBCAN2, 0, 0, motor_enable, 1);
cout << "电机使能成功" << endl;
}
/*速度模式运动*/
void speed_action(uint32_t motor_id, int32_t data)
{
motor_init(motor_id); // 电机初始化清除错误!
motor_mode(2, motor_id); /*选择速度模式*/
motor_enable(motor_id); /*电机使能*/
acceleration_set(300, motor_id); /*设置加速度*/
speed_set(2, data, motor_id); /*设置速度模式下的速度*/
cout << "电机运动" << endl;
}
void callback(const geometry_msgs::Twist &msg)
{
double wl = 0;
double wr = 0;
double vl = (msg.linear.x+msg.angular.z*robot_l/2)*100;//电机线速度 m/s
double vr = (msg.linear.x-msg.angular.z*robot_l/2)*100;
wl = vl/WHEEL_RADIUS ;//度/s
wr = vr/WHEEL_RADIUS ;
ROS_INFO_STREAM("wl is :" << wl);
ROS_INFO_STREAM("wr is :" << wr);
speed_action(0x608, wl);
usleep(500);
speed_action(0x607, -wr);
usleep(10000); // 延时0.5ms,确保前一个节点消息发送完毕,避免发送冲突
}