Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include "RobChair.h"
00039 
00040 RobChair::RobChair()
00041 {
00042     
00043 }
00044 
00045 RobChair::~RobChair()
00046 {
00047     turnTriggerOff();
00048     
00049     turnPDrivesOff();
00050     turnEncodersOff();
00051 }
00052 
00053 void RobChair::initializeRobChair(ros::Publisher * can_pub, double kp, double ki)
00054 {
00055     can_pub_ = can_pub;
00056     
00057     got_left_encoder_data_ = false;
00058     got_right_encoder_data_ = false;
00059     
00060     n_ = 0;
00061     
00062     x_ = 0.0;
00063     y_ = 0.0;
00064     yaw_ = 0.0;
00065     linear_velocity_ = 0.0;
00066     angular_velocity_ = 0.0;
00067     
00068     char data = 1;
00069     
00070     sendCANFrame(RobChair::BothPDrives, RobChair::SetPDriveControlMode, &data, 1);
00071     
00072     sendCANFrame(RobChair::BothEncoders, RobChair::SetEncoderControlMode, &data, 1);
00073     
00074     if(kp>0.0 && ki>0.0)
00075     {
00076         setPIControlValues(RobChair::BothEncoders, kp, ki);
00077     }
00078     
00079     turnEncodersOn();
00080     turnPDrivesOn();
00081     
00082     turnTriggerOn();
00083 }
00084 
00085 void RobChair::setPIControlValues(RobChairDS destination, double kp, double ki)
00086 {
00087     
00088     long kp_int = kp*1000;
00089     long ki_int = ki*1000;
00090     
00091     char data[8];
00092     
00093     memset(data, kp_int, 4);
00094     memset(data+4, ki_int, 4);
00095     
00096     sendCANFrame(destination, RobChair::SetPIControlValues, data, 8);
00097 }
00098 
00099 void RobChair::setVelocities(double linear_velocity, double angular_velocity)
00100 {
00101     double delta_v = (ROBCHAIR_AXLE_LENGTH * angular_velocity)/2.0;
00102     
00103     
00104     double left_velocity = ((linear_velocity - delta_v)/ROBCHAIR_WHEEL_RADIUS) * ROBCHAIR_K;
00105     
00106         double right_velocity = ((linear_velocity + delta_v)/ROBCHAIR_WHEEL_RADIUS) * ROBCHAIR_K;
00107     
00108     char data[2];
00109     
00110     data[0] = static_cast<int>(left_velocity) & 0x0FF;
00111     data[1] = (static_cast<int>(left_velocity) >> 8) & 0x0FF;
00112     
00113     sendCANFrame(RobChair::LeftEncoder, RobChair::SetVelocityValue, data, 2, 3);
00114     
00115     data[0] = static_cast<int>(right_velocity) & 0x0FF;
00116     data[1] = (static_cast<int>(right_velocity) >> 8) & 0x0FF;
00117     
00118     sendCANFrame(RobChair::RightEncoder, RobChair::SetVelocityValue, data, 2, 3);
00119 }
00120 
00121 void RobChair::decodeEncoderData(RobChairDS encoder, const can_msgs::CANFrame::ConstPtr& msg)
00122 {
00123     double temp_wheel_position;
00124         double temp_wheel_velocity;
00125     
00126     temp_wheel_position = (static_cast<int>(msg->data[3]) << 24) + (static_cast<int>(msg->data[2]) << 16) + (static_cast<int>(msg->data[1]) << 8) + static_cast<int>(msg->data[0]);
00127         temp_wheel_velocity = (static_cast<int>(msg->data[5]) << 8) + static_cast<int>(msg->data[4]);
00128     
00129     temp_wheel_position = static_cast<double>(temp_wheel_position)*(ROBCHAIR_CONTROL_PERIOD/ROBCHAIR_K);
00130         temp_wheel_velocity = static_cast<double>(temp_wheel_velocity)*(1/ROBCHAIR_K);
00131                              
00132     if(encoder == RobChair::LeftEncoder)
00133     {
00134         last_left_wheel_position_ = left_wheel_position_;
00135         left_wheel_position_ = temp_wheel_position * ROBCHAIR_WHEEL_RADIUS;
00136         left_wheel_velocity_ = temp_wheel_velocity * ROBCHAIR_WHEEL_RADIUS;
00137         got_left_encoder_data_ = true;
00138     }
00139     else if(encoder == RobChair::RightEncoder)
00140     {
00141         last_right_wheel_position_ = right_wheel_position_;
00142         right_wheel_position_ = temp_wheel_position * ROBCHAIR_WHEEL_RADIUS;
00143         right_wheel_velocity_ = temp_wheel_velocity * ROBCHAIR_WHEEL_RADIUS;
00144         got_right_encoder_data_ = true;
00145     }
00146     
00147     
00148     if(got_left_encoder_data_ && got_left_encoder_data_)
00149     {
00150         double delta_phi_left = left_wheel_position_ - last_left_wheel_position_;
00151         double delta_phi_right = right_wheel_position_ - last_right_wheel_position_;
00152         
00153         double delta_s = (delta_phi_right + delta_phi_left)/2;
00154         double delta_theta = (delta_phi_right - delta_phi_left)/ROBCHAIR_AXLE_LENGTH;
00155 
00156         double half_theta = limitAngle(yaw_ + delta_theta/2);
00157         
00158         x_ += delta_s * cos(half_theta);
00159         y_ += delta_s * sin(half_theta);
00160         yaw_ = limitAngle(yaw_ + delta_theta);
00161         
00162         linear_velocity_ = (right_wheel_velocity_ + left_wheel_velocity_)/2;
00163         angular_velocity_ = (right_wheel_velocity_ - left_wheel_velocity_)/ROBCHAIR_AXLE_LENGTH;
00164         
00165         got_left_encoder_data_ = false;
00166         got_right_encoder_data_ = false;
00167     }
00168 }
00169 
00170 void RobChair::sendCANFrame(RobChairDS destination, char function, char * data, int data_count, char n)
00171 {
00172     can_msgs::CANFrame frame;
00173     
00174     frame.stamp = ros::Time::now();
00175     
00176     frame.id = destination << 7 + RobChair::PC << 4 + function;
00177     frame.data.resize(data_count);
00178     for(int i=0 ; i<data_count ; i++)
00179     {
00180         frame.data[i] = data[i];
00181     }
00182     
00183     
00184     if(n>0 && n<=5)
00185     {
00186         
00187         while(n_!=n)
00188         {
00189             ros::Duration(ROBCHAIR_CONTROL_PERIOD/5.0/10.0).sleep();
00190         }
00191     }
00192     
00193     can_pub_->publish(frame);
00194 }
00195 
00196 void RobChair::receivedCANFrame(const can_msgs::CANFrame::ConstPtr& msg)
00197 {
00198     ROS_INFO("RobChair - %s - Got a message!", __FUNCTION__);
00199     
00200     
00201     char function = msg->id & ROBCHAIR_FUNCTION_MASK;
00202     char source = msg->id & ROBCHAIR_SOURCE_MASK;
00203     char destination = msg->id & ROBCHAIR_DESTINATION_MASK;
00204     
00205     ROS_INFO("RobChair - %s - D:%d S:%d F:%d", __FUNCTION__, destination, source, function);
00206 
00207     
00208     if(destination != RobChair::PC) return;
00209     
00210     
00211     switch(source)
00212     {
00213         case RobChair::RightEncoder:
00214             if(function == RobChair::DataFromEncoder)
00215             {
00216                 decodeEncoderData(RobChair::RightEncoder, msg);
00217             }
00218             break;
00219         
00220         case RobChair::LeftEncoder:
00221             if(function == RobChair::DataFromEncoder)
00222             {
00223                 decodeEncoderData(RobChair::LeftEncoder, msg);
00224             }
00225             break;
00226             
00227         case RobChair::SyncMCU:
00228             if(function == RobChair::SyncronizeAllNodes)
00229             {
00230                 n_ = msg->data[0];
00231             }
00232             break;
00233             
00234         default:
00235             ROS_ERROR("RobChair - %s - Got CAN frame from an unknown source: %d", __FUNCTION__, source);
00236             break;
00237     }
00238 }
00239 
00240 double RobChair::limitAngle(double angle)
00241 {
00242     double correct_angle;
00243     
00244     if(angle > M_PI)
00245     {
00246         correct_angle = angle - 2 * M_PI;
00247     }
00248     else if(angle < - M_PI)
00249     {
00250         correct_angle = angle + 2 * M_PI;
00251     }
00252     else
00253     {
00254         correct_angle = angle;
00255     }
00256     
00257     return correct_angle;
00258 }
00259 
00260 
00261