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