文章目录
前言
前面学习了ROS的基本操作,仅仅只使用这个操作系统并没有什么用处,还需要讲他与硬件相结合从而控制机器人的运动。`
一、两种控制器的功能
ROS主控采用的Jetson nano B01 STM32主控用的是F407,通过Jetson 驱动雷达采集信息,然后串口像STM32发送相关的运动指令,串口接收到后执行相应的动作。
二、硬件连接
硬件连接很简单用的是平衡小车之家的ROS STM32控制板,其内置电平转换芯片,只需用一根USB数据线连接起来即可。
构造函数和析构函数是类的另一种操作,首先获取STM32数据也就是获取陀螺仪数据,然后计算出四元素,将相关信息发送给STM32
turn_on_robot::~turn\_on\_robot()
{
//Sends the stop motion command to the lower machine before the turn\_on\_robot object ends
//瀵硅薄turn\_on\_robot缁撴潫鍓嶅悜涓嬩綅鏈哄彂閫佸仠姝㈣繍鍔ㄥ懡浠?
Send_Data.tx[0]=FRAME_HEADER;
Send_Data.tx[1] = 0;
Send_Data.tx[2] = 0;
//The target velocity of the X-axis of the robot //鏈哄櫒浜篨杞寸殑鐩爣绾块€熷害
Send_Data.tx[4] = 0;
Send_Data.tx[3] = 0;
//The target velocity of the Y-axis of the robot //鏈哄櫒浜篩杞寸殑鐩爣绾块€熷害
Send_Data.tx[6] = 0;
Send_Data.tx[5] = 0;
//The target velocity of the Z-axis of the robot //鏈哄櫒浜篫杞寸殑鐩爣瑙掗€熷害
Send_Data.tx[8] = 0;
Send_Data.tx[7] = 0;
Send_Data.tx[9]=Check\_Sum(9,SEND_DATA_CHECK); //Check the bits for the Check\_Sum function //鏍¢獙浣嶏紝瑙勫垯鍙傝Check\_Sum鍑芥暟
Send_Data.tx[10]=FRAME_TAIL;
try
{
Stm32_Serial.write(Send_Data.tx,sizeof (Send_Data.tx)); //Send data to the serial port //鍚戜覆鍙e彂鏁版嵁
}
catch (serial::IOException& e)
{
ROS\_ERROR\_STREAM("Unable to send data through serial port"); //If sending data fails, an error message is printed //濡傛灉鍙戦€佹暟鎹け璐?鎵撳嵃閿欒淇℃伅
}
Stm32_Serial.close(); //Close the serial port //鍏抽棴涓插彛
ROS\_INFO\_STREAM("Shutting down"); //Prompt message //鎻愮ず淇℃伅
}
uart.c
#include "usartx.h"
SEND_DATA Send_Data;
RECEIVE_DATA Receive_Data;
extern int Time_count;
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
Function: Usartx3, Usartx1 and CAN send data task
Input : none
Output : none
º¯Êý¹¦ÄÜ£º´®¿Ú3¡¢´®¿Ú1¡¢´®¿Ú5¡¢CAN·¢ËÍÊý¾ÝÈÎÎñ
Èë¿Ú²ÎÊý£ºÎÞ
·µ»Ø Öµ£ºÎÞ
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void data\_task(void \*pvParameters)
{
u32 lastWakeTime = getSysTickCnt();
while(1)
{
//The task is run at 20hz
//´ËÈÎÎñÒÔ20HzµÄƵÂÊÔËÐÐ
vTaskDelayUntil(&lastWakeTime, F2T(RATE_20_HZ));
//Assign the data to be sent
//¶ÔÒª½øÐз¢Ë͵ÄÊý¾Ý½øÐи³Öµ
data\_transition();
USART1\_SEND(); //Serial port 1 sends data //´®¿Ú1·¢ËÍÊý¾Ý
USART3\_SEND(); //Serial port 3 (ROS) sends data //´®¿Ú3(ROS)·¢ËÍÊý¾Ý
USART5\_SEND(); //Serial port 5 sends data //´®¿Ú5·¢ËÍÊý¾Ý
CAN\_SEND(); //CAN send data //CAN·¢ËÍÊý¾Ý
}
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
Function: The data sent by the serial port is assigned
Input : none
Output : none
º¯Êý¹¦ÄÜ£º´®¿Ú·¢Ë͵ÄÊý¾Ý½øÐи³Öµ
Èë¿Ú²ÎÊý£ºÎÞ
·µ»Ø Öµ£ºÎÞ
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void data\_transition(void)
{
Send_Data.Sensor_Str.Frame_Header = FRAME_HEADER; //Frame\_header //Ö¡Í·
Send_Data.Sensor_Str.Frame_Tail = FRAME_TAIL; //Frame\_tail //֡β
//According to different vehicle types, different kinematics algorithms were selected to carry out the forward kinematics solution,
//and the three-axis velocity was obtained from each wheel velocity
//¸ù¾Ý²»Í¬³µÐÍÑ¡Ôñ²»Í¬Ô˶¯Ñ§Ëã·¨½øÐÐÔ˶¯Ñ§Õý½â£¬´Ó¸÷³µÂÖËÙ¶ÈÇó³öÈýÖáËÙ¶È
switch(Car_Mode)
{
case Mec_Car:
Send_Data.Sensor_Str.X_speed = ((MOTOR_A.Encoder+MOTOR_B.Encoder+MOTOR_C.Encoder+MOTOR_D.Encoder)/4)\*1000;
Send_Data.Sensor_Str.Y_speed = ((MOTOR_A.Encoder-MOTOR_B.Encoder+MOTOR_C.Encoder-MOTOR_D.Encoder)/4)\*1000;
Send_Data.Sensor_Str.Z_speed = ((-MOTOR_A.Encoder-MOTOR_B.Encoder+MOTOR_C.Encoder+MOTOR_D.Encoder)/4/(Axle_spacing+Wheel_spacing))\*1000;
break;
case Omni_Car:
Send_Data.Sensor_Str.X_speed = ((MOTOR_C.Encoder-MOTOR_B.Encoder)/2/X_PARAMETER)\*1000;
Send_Data.Sensor_Str.Y_speed = ((MOTOR_A.Encoder\*2-MOTOR_B.Encoder-MOTOR_C.Encoder)/3)\*1000;
Send_Data.Sensor_Str.Z_speed = ((MOTOR_A.Encoder+MOTOR_B.Encoder+MOTOR_C.Encoder)/3/Omni_turn_radiaus)\*1000;
break;
case Akm_Car:
Send_Data.Sensor_Str.X_speed = ((MOTOR_A.Encoder+MOTOR_B.Encoder)/2)\*1000;
Send_Data.Sensor_Str.Y_speed = 0;
Send_Data.Sensor_Str.Z_speed = ((MOTOR_B.Encoder-MOTOR_A.Encoder)/Wheel_spacing)\*1000;
break;
case Diff_Car:
Send_Data.Sensor_Str.X_speed = ((MOTOR_A.Encoder+MOTOR_B.Encoder)/2)\*1000;
Send_Data.Sensor_Str.Y_speed = 0;
Send_Data.Sensor_Str.Z_speed = ((MOTOR_B.Encoder-MOTOR_A.Encoder)/Wheel_spacing)\*1000;
break;
case FourWheel_Car:
Send_Data.Sensor_Str.X_speed = ((MOTOR_A.Encoder+MOTOR_B.Encoder+MOTOR_C.Encoder+MOTOR_D.Encoder)/4)\*1000;
Send_Data.Sensor_Str.Y_speed = 0;
Send_Data.Sensor_Str.Z_speed = ((-MOTOR_B.Encoder-MOTOR_A.Encoder+MOTOR_C.Encoder+MOTOR_D.Encoder)/2/(Axle_spacing+Wheel_spacing))\*1000;
break;
case Tank_Car:
Send_Data.Sensor_Str.X_speed = ((MOTOR_A.Encoder+MOTOR_B.Encoder)/2)\*1000;
Send_Data.Sensor_Str.Y_speed = 0;
Send_Data.Sensor_Str.Z_speed = ((MOTOR_B.Encoder-MOTOR_A.Encoder)/(Wheel_spacing)\*10