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
00037 #include "USBInterface.h"
00038
00039 #include <iostream>
00040 using std::cout;
00041 using std::endl;
00042
00043 int USBPololuInterface::MOVE_TARGET_TIMEOUT = 1000;
00044 int USBPololuInterface::MOVE_TARGET_MAX_TRYS = 1000;
00045
00046 USBPololuInterface::USBPololuInterface(uint16_t v_id, uint16_t p_id)
00047 : m_device(0), m_context(0), m_deviceHandle(0)
00048 {
00049
00050 libusb_init(&m_context);
00051
00052
00053 struct libusb_device **devs;
00054 struct libusb_device_descriptor info;
00055
00056
00057 int count = libusb_get_device_list(m_context,&devs);
00058
00059
00060 int pololuCount = 0;
00061 for (int i = 0; i < count;i++)
00062 {
00063 libusb_get_device_descriptor(devs[i],&info);
00064
00065 if(info.idVendor == v_id && info.idProduct == p_id)
00066 {
00067 pololuCount++;
00068 m_device = devs[i];
00069 }
00070 }
00071
00072
00073 if(pololuCount > 1)
00074 {
00075 cout << "USBPololuInterface: Detected " << pololuCount << "boards. Using last detected one." << endl;
00076 }
00077
00078
00079 int ret = -1;
00080 if(m_device)
00081 {
00082 ret = libusb_open(m_device, &m_deviceHandle);
00083 }
00084
00085 if(ret < 0)
00086 {
00087 cout << "USBPololuInterface: Unable to open device." << endl;
00088 }
00089
00090 }
00091
00092
00093
00094 string USBPololuInterface::getErrorDescription(int code)
00095 {
00096 switch(code)
00097 {
00098 case -1:
00099 return "I/O error.";
00100 case -2:
00101 return "Invalid parameter.";
00102 case -3:
00103 return "Access denied.";
00104 case -4:
00105 return "Device does not exist.";
00106 case -5:
00107 return "No such entity.";
00108 case -6:
00109 return "Busy.";
00110 case -7:
00111 return "Timeout.";
00112 case -8:
00113 return "Overflow.";
00114 case -9:
00115 return "Pipe error.";
00116 case -10:
00117 return "System call was interrupted.";
00118 case -11:
00119 return "Out of memory.";
00120 case -12:
00121 return "Unsupported/unimplemented operation.";
00122 case -99:
00123 return "Other error.";
00124 default:
00125 return "Unknown error code.";
00126 };
00127 }
00128
00129 void USBPololuInterface::controlTransfer(char requestType, char request, ushort value, ushort index)
00130 {
00131 if(m_deviceHandle)
00132 {
00133 int result = libusb_control_transfer(
00134 m_deviceHandle,
00135 requestType,
00136 request,
00137 value,
00138 index,
00139 0, 0, 5000);
00140
00141 if(result < 0)
00142 {
00143 cout << "USBPololuInterface::controlTransfer(): " << getErrorDescription(result) << endl;
00144 }
00145 }
00146 else
00147 {
00148 cout << "USBPololuInterface::controlTransfer(): Device not open." << endl;
00149 }
00150 }
00151
00152 void USBPololuInterface::controlTransfer(
00153 char requestType,
00154 char request,
00155 ushort value,
00156 ushort index,
00157 unsigned char* data,
00158 ushort length)
00159 {
00160 if(m_deviceHandle)
00161 {
00162 int result = libusb_control_transfer(
00163 m_deviceHandle,
00164 requestType,
00165 request,
00166 value,
00167 index,
00168 data, length, 5000);
00169
00170 if(result < 0)
00171 {
00172 cout << "USBPololuInterface::controlTransfer(): " << getErrorDescription(result) << endl;
00173 }
00174 }
00175 else
00176 {
00177 cout << "USBPololuInterface::controlTransfer(): Device not open." << endl;
00178 }
00179 }
00180
00181
00182 uint8_t USBPololuInterface::channelToPort(uint8_t channel)
00183 {
00184 if (channel <= 3)
00185 {
00186 return channel;
00187 }
00188 else if (channel < 6)
00189 {
00190 return uint8_t(channel + 2);
00191 }
00192 cout << "USBPololuInterface::channelToPort(): Unsupported channel: << " << channel << endl;
00193 return 0;
00194 }
00195
00196
00197 void USBPololuInterface::setRawParameter(ushort parameter, ushort value, int bytes)
00198 {
00199 ushort index = (ushort)((bytes << 8) + parameter);
00200 controlTransfer(0x40, uscRequest::REQUEST_SET_PARAMETER, value, index);
00201 }
00202
00203
00204 uscParameter USBPololuInterface::specifyServo(uscParameter p, uint8_t servo)
00205 {
00206 return (uscParameter)((uint8_t)(p) + servo * servoParameterBytes);
00207 }
00208
00209 uint8_t USBPololuInterface::normalSpeedToExponentialSpeed(ushort normalSpeed)
00210 {
00211 ushort mantissa = normalSpeed;
00212 uint8_t exponent = 0;
00213
00214 while (true)
00215 {
00216 if (mantissa < 32)
00217 {
00218
00219 return (uint8_t)(exponent + (mantissa << 3));
00220 }
00221
00222 if (exponent == 7)
00223 {
00224
00225 return 0xFF;
00226 }
00227
00228
00229 exponent += 1;
00230 mantissa >>= 1;
00231 }
00232 }
00233
00234 void USBPololuInterface::setUscSettings(uscSettings settings)
00235 {
00236
00237 setRawParameter(uscParameter::PARAMETER_SCRIPT_DONE, (ushort)(settings.scriptDone ? 1 : 0), sizeof(ushort));
00238 setRawParameter(uscParameter::PARAMETER_SERVOS_AVAILABLE, settings.servosAvailable, sizeof(uint8_t));
00239 setRawParameter(uscParameter::PARAMETER_SERVO_PERIOD, settings.servoPeriod, sizeof(uint8_t));
00240
00241
00242 uint8_t ioMask = 0;
00243 uint8_t outputMask = 0;
00244
00245 std::list<channelSetting>::iterator it;
00246
00247 int i = 0;
00248 for(it = settings.channelSettings.begin(); it != settings.channelSettings.end(); it++)
00249 {
00250 channelSetting setting = *it;
00251
00252
00253 if (setting.mode == ChannelMode::Input || setting.mode == ChannelMode::Output)
00254 {
00255 ioMask |= (uint8_t)(1 << channelToPort(i));
00256 }
00257
00258 if (setting.mode == ChannelMode::Output)
00259 {
00260 outputMask |= (uint8_t)(1 << channelToPort(i));
00261 }
00262
00263
00264
00265
00266
00267 HomeMode correctedHomeMode = setting.homeMode;
00268 if (setting.mode == ChannelMode::Input)
00269 {
00270 correctedHomeMode = HomeMode::Ignore;
00271 }
00272
00273
00274 ushort home;
00275 if (correctedHomeMode == HomeMode::Off) home = 0;
00276 else if (correctedHomeMode == HomeMode::Ignore) home = 1;
00277 else home = setting.home;
00278
00279 setRawParameter(specifyServo(uscParameter::PARAMETER_SERVO0_HOME, i), home, sizeof(ushort));
00280 setRawParameter(specifyServo(uscParameter::PARAMETER_SERVO0_MIN, i), (ushort)(setting.minimum / 64), sizeof(ushort));
00281 setRawParameter(specifyServo(uscParameter::PARAMETER_SERVO0_MAX, i), (ushort)(setting.maximum / 64), sizeof(ushort));
00282 setRawParameter(specifyServo(uscParameter::PARAMETER_SERVO0_NEUTRAL, i), setting.neutral, sizeof(uint16_t));
00283 setRawParameter(specifyServo(uscParameter::PARAMETER_SERVO0_RANGE, i), (ushort)(setting.range / 127), sizeof(ushort));
00284 setRawParameter(specifyServo(uscParameter::PARAMETER_SERVO0_SPEED, i), normalSpeedToExponentialSpeed(setting.speed), sizeof(uint16_t));
00285 setRawParameter(specifyServo(uscParameter::PARAMETER_SERVO0_ACCELERATION, i), setting.acceleration, sizeof(uint8_t));
00286 }
00287
00288 setRawParameter(uscParameter::PARAMETER_IO_MASK_C, ioMask, sizeof(uint8_t));
00289 setRawParameter(uscParameter::PARAMETER_OUTPUT_MASK_C, outputMask, sizeof(uint8_t));
00290
00291 }
00292
00293
00294
00295
00296
00297 void USBPololuInterface::getServoStatus(int servo, servoStatus& status)
00298 {
00299
00300 int packet_size = sizeof(maestroStatus) + 6 * sizeof(servoStatus);
00301 unsigned char* buffer = new unsigned char[packet_size];
00302
00303
00304 controlTransfer(0xC0, REQUEST_GET_VARIABLES, 0, 0, buffer, packet_size);
00305
00306
00307 unsigned char* p = buffer;
00308 servoStatus servos[6];
00309 for(int i = 0; i < 6; i++)
00310 {
00311 servos[i] = *(servoStatus*)(p + sizeof(maestroStatus) + sizeof(servoStatus) * i);
00312 }
00313
00314
00315 status.position = servos[servo].position / 4;
00316 status.target = servos[servo].target / 4;
00317 status.speed = servos[servo].speed;
00318 status.acceleration = servos[servo].acceleration;
00319 }
00320
00321 void USBPololuInterface::setTarget(int servo, ushort value)
00322 {
00323
00324
00325 controlTransfer(0x40, REQUEST_SET_TARGET, 4.0 * value, servo);
00326 }
00327
00328 void USBPololuInterface::moveToTarget(int servo, ushort target)
00329 {
00330 setTarget(servo, target);
00331 servoStatus status;
00332
00333
00334 int i = 0;
00335 do
00336 {
00337 usleep(MOVE_TARGET_TIMEOUT);
00338 getServoStatus(servo, status);
00339 i++;
00340 }
00341 while(status.position != target && i < MOVE_TARGET_MAX_TRYS);
00342
00343
00344 if(i == MOVE_TARGET_MAX_TRYS)
00345 {
00346 cout << "USBPololuInterface::moveToTarget(): Timeout. Target position " << target << " out of servo range?" << endl;
00347 }
00348 }
00349
00350 void USBPololuInterface::moveToTarget(int servo, ushort target, ushort time)
00351 {
00352 servoStatus status;
00353 getServoStatus(servo, status);
00354
00355
00356 int steps = std::fabs(status.position - target);
00357 int timeout = time * 1000 / steps;
00358
00359
00360 int initialPosition = status.position;
00361 int factor = 1;
00362 if(initialPosition > target) factor *= -1;
00363
00364
00365 for(int i = 0; i <= steps; i++)
00366 {
00367 setTarget(servo, initialPosition + factor * i);
00368 usleep(timeout);
00369 }
00370
00371 }
00372
00373 void USBPololuInterface::setSpeed(int servo, ushort value)
00374 {
00375 controlTransfer(0x40, REQUEST_SET_SERVO_VARIABLE, value, servo);
00376 }
00377
00378 USBPololuInterface::~USBPololuInterface()
00379 {
00380
00381 if(m_deviceHandle)
00382 {
00383 libusb_close(m_deviceHandle);
00384 }
00385
00386
00387 if(m_context)
00388 {
00389 libusb_exit(m_context);
00390 }
00391
00392
00393 }