AGV using ros with TROY motor

Dependencies:   mbed ros_lib_kinetic

main.cpp

Committer:
WeberYang
Date:
2018-05-02
Revision:
2:fcf8a7739eed
Parent:
0:85456b971234

File content as of revision 2:fcf8a7739eed:

#include "mbed.h"
#include <ros.h>
#include <ros/time.h>
#include <std_msgs/Empty.h>
#include <std_msgs/String.h>
#include<geometry_msgs/Twist.h> //set buffer larger than 50byte
#include <std_msgs/Float32.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#define Start 0xAA
#define Address 0x7F
#define ReturnType 0x00
#define Clean 0x00
#define Reserve 0x00
#define End 0x55 

    Serial RS232 (PB_10, PB_11,115200);  // This one works
    std_msgs::String str_msg;
    std_msgs::Float32 VelAngular_L;
    std_msgs::Float32 VelAngular_R;

// ============= =============
        float motor_rpm_r, motor_rpm_l;
// ============= =============
        
    ros::Publisher pub_lmotor("pub_lmotor", &VelAngular_L);
    ros::Publisher pub_rmotor("pub_rmotor", &VelAngular_R);
    int seq = 0; // monitor times of callbacks
    int old_seq = 0; // monitor times of the command
    
    
    ros::NodeHandle nh;
    geometry_msgs::Twist vel;
    //float left;
    //float right;
    float Lrpm,Rrpm;
    float ticks_since_target;
    double timeout_ticks;

    double w;
    double rate;
    double Dimeter;
    float dx,dy,dr;
    void init_variables();
void Sendmessage(float Rrpm,float Lrpm);

unsigned int CRC_Verify(unsigned char *cBuffer, unsigned int iBufLen)
{
    unsigned int i, j;
    //#define wPolynom 0xA001
    unsigned int wCrc = 0xffff;
    unsigned int wPolynom = 0xA001;
    /*---------------------------------------------------------------------------------*/
    for (i = 0; i < iBufLen; i++)
    {
        wCrc ^= cBuffer[i];
        for (j = 0; j < 8; j++)
        {
            if (wCrc &0x0001)
            {
                wCrc = (wCrc >> 1) ^ wPolynom;
            }
            else
            { 
                wCrc = wCrc >> 1;
            }
        }
    }
    return wCrc;
}

 /*
 起始碼(1Byte):                            AA
地址碼(1Byte):                             01
返回數據類型(1Byte):從站驅動器不返回數據       00
故障清除(1Byte)默認發送:                     00
保留位(1Byte)                              00
A 馬達過載控制(1Byte)驅動器使能狀態           01
B 馬達控制(1Byte)                           01
A 運行方向(1Byte)00:正轉,01反轉             00
B 運行方向(1Byte)00:正轉,01反轉             00
運行轉速(2Byte)是100–3000r/min,            12 34
運行轉速(2Byte)是100–3000r/min,            12 34
第 1 個 Byte:速度值高 8 位;                
第 2 個 Byte:速度值低 8 位;
無效(2Byte)00:無效數據位。                   00
結束碼(1Byte)55:通訊結束編碼識別。            55
校驗碼(2Byte)CRC16 
 */

 //   void spinOnce();
 //   void twistCallback(const geometry_msgs::Twist &twist_aux);


void init_variables()
{
    dx = dy = dr =0;
    w = 0.302;//0.2 ;//m
    rate = 20;//50;
    timeout_ticks = 2;
    Dimeter = 0.127;//0.15;
}
void Sendmessage(float Rrpm,float Lrpm)
{
    //RS232.printf("Wr = %.1f\n",Rrpm);
    //RS232.printf("Wl = %.1f\n",Lrpm);
unsigned char sendData[16];
unsigned int tmpCRC;
int motor1,motor2;
   
    sendData[0] = Start;
    sendData[1] = Address;
    sendData[2] = ReturnType;
    sendData[3] = Clean;
    sendData[4] = Reserve;
    sendData[5]  = 0x01;//motor1Sevro ON
    sendData[6] = 0x01;//motor2Sevro ON
if (Rrpm>0){sendData[7] = 0x01;}else{sendData[7] = 0x00;}
if (Lrpm>0){sendData[8] = 0x00;}else{sendData[8] = 0x01;}
   motor1 =  abs(Rrpm);
   motor2 =  abs(Lrpm); 
    
    sendData[9] = (motor1>>8);//motor1speedH
    sendData[10] = (motor1 & 0xFF);//motor1speedL
    sendData[11] = (motor2>>8);//motor2speedH
    sendData[12] = (motor2 & 0xFF);//motor2speedL
    sendData[13] = End;
    tmpCRC = CRC_Verify(sendData, 14);
    sendData[14] = (tmpCRC & 0xFF);
    sendData[15] = (tmpCRC>>8);
    int i;
    for (i=0;i<16;i++)
    {
        RS232.printf("%c",sendData[i]);
    }
    RS232.printf("\r\n");
}


int myabs( int a ){
    if ( a < 0 ){
        return -a;
        }
        return a;
        }
        
        
        
void TwistToMotors()
{
    old_seq = seq;
    seq = seq + 1;    
    //int lower_bound = 100;
    //int upper_bound = 300;
    float right,left;
//    float motor_rpm_r, motor_rpm_l;
    //double vel_data[2];
    float vel_data[2];
    float motor_rpm_vx, motor_rpm_theta, motor_rpm_v;

    // prevent agv receive weird 1.0 command from cmd_vel

    right = ( 1.0 * dx ) + (dr * w /2);
    left = ( 1.0 * dx ) - (dr * w /2);
    motor_rpm_v = ( 1.0 * dx )*rate/(Dimeter/2)*60/(2*3.1416);
    
    if((motor_rpm_v!=0) && (myabs(motor_rpm_v)<100)){
        if (motor_rpm_v > 0)  motor_rpm_v=100;
        else motor_rpm_v = -100;
        }

    motor_rpm_theta=(dr * w /2)*rate/(Dimeter/2)*60/(2*3.1416);


    //motor_rpm_r = right*rate/(Dimeter/2)*60/(2*3.1416);
    //motor_rpm_l =  left*rate/(Dimeter/2)*60/(2*3.1416);

    motor_rpm_r = motor_rpm_v + motor_rpm_theta;
    motor_rpm_l = motor_rpm_v - motor_rpm_theta;
    
        
        if (myabs(motor_rpm_r)<100 || myabs(motor_rpm_l)<100){
            
        if(dx == 0){
            if(dr > 0){
                motor_rpm_r = 100;
                motor_rpm_l = -100;
                }else if( dr < 0 ){
                    motor_rpm_r = -100;
                    motor_rpm_l = 100;
                    }else{
                        motor_rpm_r = 0;
                        motor_rpm_l = 0;
                        }
            }
            else if( dx > 0 ){
                if( myabs(motor_rpm_r) < 100 ){
                    motor_rpm_r = 100;
                    motor_rpm_l=motor_rpm_l+(100-motor_rpm_r);
                }
                if ( myabs(motor_rpm_l) < 100 ){
                    motor_rpm_l = 100;
                    motor_rpm_r=motor_rpm_r+(100-motor_rpm_l);
                    }
            }else{
                    if ( myabs(motor_rpm_r) < 100 ){
                        motor_rpm_r = -100;
                        motor_rpm_l=motor_rpm_l+(-100-motor_rpm_r);
                    }
                    
                    if (myabs(motor_rpm_l) < 100 ){
                        motor_rpm_l = -100;
                        motor_rpm_r=motor_rpm_r+(-100-motor_rpm_l);
                    }
            }
    }
                                 
    /*
    if ( myabs(motor_rpm_r) == myabs(motor_rpm_l) && myabs(motor_rpm_r) < 100){
        int s = myabs(motor_rpm_r);
        
        motor_rpm_r = motor_rpm_r / s * 101;
        motor_rpm_l = motor_rpm_l / s * 101;
        
        }
*/

/*
    if ( myabs(vel_data[0]) < lower_bound )
    { // if right wheel rpm < lower_bound
            int a = 0;
            a = lower_bound - myabs( vel_data[0] );
        
        if (vel_data[0] > 0)
        {
            vel_data[0] = lower_bound;
        }
        else
        {
            vel_data[0] = -lower_bound;
        }
            
            
        if (vel_data[1] > 0)
        {
            vel_data[1] = vel_data[1] + a;
        }
        else
        {
            vel_data[1] = vel_data[1] - a;
        } //
        
    }
        
    else if ( myabs(vel_data[0]) > upper_bound )
    {  // if right wheel rpm > upper_bound
            int a = 0;
            a = myabs( vel_data[0] ) - upper_bound;
        
        if (vel_data[0] > 0)
        {
            vel_data[0] = upper_bound;
        }
        else
        {
            vel_data[0] = -upper_bound;
        }
            
            
        if (vel_data[1] > 0)
        {
            vel_data[1] = vel_data[1] - a;
        }
        else
        {
            vel_data[1] = vel_data[1] + a;
        }
    }
        
               
    if ( myabs(vel_data[1]) < lower_bound )
    { // if left wheel rpm < lower_bound
            int a = 0;
            a = lower_bound - myabs( vel_data[1] );
        
        if (vel_data[1] > 0)
        {
            vel_data[1] = lower_bound;
        }
        else
        {
            vel_data[1] = -lower_bound;
        }
            
            
        if (vel_data[0] > 0)
        {
            vel_data[0] = vel_data[0] + a;
        }
        else
        {
            vel_data[0] = vel_data[0] - a;
        } //
    }
        
        
    else if (myabs(vel_data[1]) > upper_bound )
    { // if left wheel rpm > upper_bound
            int a = 0;
            a = myabs( vel_data[1] ) - upper_bound;
        
        if (vel_data[1] > 0)
        {
            vel_data[1] = upper_bound;
        }
        else
        {
            vel_data[1] = -upper_bound;
        }
            
            
        if (vel_data[0] > 0)
        {
            vel_data[0] = vel_data[0] - a;
        }
        else
        {
            vel_data[0] = vel_data[0] + a;
        }
            
    }
               
        */
        
        /*
        if ( myabs(motor_rpm_r) < 100 || myabs(motor_rpm_l) < 100 ){
            float a = 0.0;
        
            if ( myabs(motor_rpm_r) < myabs(motor_rpm_l) ){
                
                if ( motor_rpm_r < 0 ){
                    a = -100 - motor_rpm_r;
                }else if( motor_rpm_r > 0) {
                    a = 100 - motor_rpm_r;
                    }else {
                        a = 0;
                }
                
                motor_rpm_r = motor_rpm_r + a;
                motor_rpm_l = motor_rpm_l + a;
                
                    
                
            }else if ( myabs(motor_rpm_r) > myabs(motor_rpm_l) ){
                
                if ( motor_rpm_l < 0 ){
                    a = -100 - motor_rpm_l;
                }else if( motor_rpm_l > 0) {
                    a = 100 - motor_rpm_l;
                    }else {
                        a = 0;
                }
                
                motor_rpm_l = motor_rpm_l + a;
                motor_rpm_r = motor_rpm_r + a;
                
            }
            
            // go straight < 100
            if ( motor_rpm_r == motor_rpm_l ){
                
                if ( motor_rpm_l < 0 ){
                    motor_rpm_l = -100;
                    motor_rpm_r = -100;
                
                
                }else if( motor_rpm_l > 0) {
                    motor_rpm_l = 100;
                    motor_rpm_r = 100;
                    }else {
                        motor_rpm_l = 0;
                        motor_rpm_r = 0;
                    }           
                
                
                }
                
                // turn < 100
                
                if ( motor_rpm_r == -motor_rpm_l ){
                
                if ( motor_rpm_l < 0 ){
                motor_rpm_l = -100;
                motor_rpm_r = 100;
                }else if( motor_rpm_l > 0) {
                motor_rpm_l = 100;
                motor_rpm_r = -100;
                }else {
                    motor_rpm_l = 0;
                    motor_rpm_r = 0;
                }
                               
            }
            //
            
            } 
            

            
        if ( myabs(motor_rpm_r) > 600 ){
               
               if ( motor_rpm_r < 0 ){
               motor_rpm_r = -100 * log( float(myabs(motor_rpm_r)) );
               }else{
                   motor_rpm_r = 100 * log( float(myabs(motor_rpm_r)) );
               }
               

               
        }
        
        if ( myabs(motor_rpm_l) > 600) {
        
               if ( motor_rpm_l < 0 ){
               motor_rpm_l = -100 * log( float(myabs(motor_rpm_l)) );
               }else{
                   motor_rpm_l = 100 * log( float(myabs(motor_rpm_l)) );
               }
        }
        
        */
        vel_data[0] = motor_rpm_r;
        vel_data[1] = motor_rpm_l;
        
        
        
        

//===================================================================
    //Sendmessage(vel_data[0],vel_data[1]);
    
    
    VelAngular_R.data = vel_data[0];
    VelAngular_L.data = vel_data[1];
    //if(VelAngular_R.data >2000 || VelAngular_L.data>2000){
    //}
    //else{
    pub_rmotor.publish( &VelAngular_R );
    pub_lmotor.publish( &VelAngular_L );
    //}
    //RS232.printf("Wr = %.1f\n",vel_data[0]);
    //RS232.printf("Wl = %.1f\n",vel_data[1]);
    ticks_since_target += 1;

}

void messageCb(const geometry_msgs::Twist &msg)
{
    ticks_since_target = 0;
    dx = msg.linear.x;
    dy = msg.linear.y;
    dr = msg.angular.z;
    //RS232.printf("dx,dy,dr= %.1f,%.1f,%.1f\n",dx,dy,dr);
    TwistToMotors();
}

void ACT( const std_msgs::String& ACT) {
char sendData[16];
//sendData = ACT;
int motor1,motor2;
   
    sendData[0] = Start;
    sendData[1] = Address;
    sendData[2] = ReturnType;
    sendData[3] = Clean;
    sendData[4] = Reserve;
    sendData[5]  = 0x00;//motor1Sevro OFF
    sendData[6] = 0x00;//motor2Sevro OFF
   motor1 =  0;
   motor2 =  0; 
    sendData[9] = (motor1>>8);//motor1speedH
    sendData[10] = (motor1 & 0xFF);//motor1speedL
    sendData[11] = (motor2>>8);//motor2speedH
    sendData[12] = (motor2 & 0xFF);//motor2speedL
    sendData[13] = End;
    
    
    sendData[14] = Start;
    sendData[15] = Start;
    int i;
    for (i=0;i<16;i++)
    {
        RS232.printf("%c",sendData[i]);
    }
    RS232.printf("\r\n");
}


ros::Subscriber<geometry_msgs::Twist> cmd_vel_sub("cmd_vel", &messageCb);
//ros::Subscriber<std_msgs::String> sub_action("ACT", &ACT );


 Timer t;
int main(int argc, char **argv)
{   
    long vel_timer = 0;
    init_variables();
    t.start();
    nh.initNode();
    nh.advertise(pub_lmotor);
    nh.advertise(pub_rmotor);
    nh.subscribe(cmd_vel_sub);
    //nh.subscribe(sub_action);

   while (true)
   {
     //if (t.read_ms() > vel_timer)
     //{
     //  vel_timer = t.read_ms() + 50;
     //  TwistToMotors();
     // }
     

     nh.spinOnce();
     
     
     if (seq +50 < old_seq){
     motor_rpm_r = 0;
     motor_rpm_l = 0;
     }
     
//     Sendmessage(-motor_rpm_r,-motor_rpm_l);
     Sendmessage(-motor_rpm_l,-motor_rpm_r);
     
     old_seq = old_seq + 1;
    
     wait_ms(10);
    
   }
}