00001
00002 #ifndef INCLUDED_SkewlZoneDriver_h_
00003 #define INCLUDED_SkewlZoneDriver_h_
00004
00005 #include "local/DeviceDriver.h"
00006 #include "local/MotionHook.h"
00007 #include "local/DataSource.h"
00008 #include "local/CommPort.h"
00009 #include "Shared/plist.h"
00010 #include "Shared/plistSpecialty.h"
00011 #include "IPC/CallbackThread.h"
00012 #include "Shared/RobotInfo.h"
00013 #include <iostream>
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <unistd.h>
00020 #include <stdlib.h>
00021 #include <libgen.h>
00022
00023 #include "rnr/rnrconfig.h"
00024 #include "rnr/new.h"
00025 #include "rnr/opts.h"
00026 #include "rnr/log.h"
00027
00028 #include "rnr/i2c.h"
00029 #include "rnr/serdev.h"
00030
00031 #include "rcb3/rcb3prot.h"
00032 #include "rcb3/rcb3lib.h"
00033
00034 #include "botsense/szFoot.h"
00035 #include "botsense/szIMU.h"
00036 #include "botsense/BotSense.h"
00037 #include "botsense/libBotSense.h"
00038
00039
00040
00041
00042
00043
00044 #define SK_EC_OK 0 ///< success exit code
00045 #define SK_EC_USAGE 2 ///< usage error exit code
00046 #define SK_EC_EXEC 4 ///< execution error exit code
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 static char *SKProxyIPAddr = "localhost";
00058 static int SKProxyIPPort = BSPROXY_LISTEN_PORT_DFT;
00059
00060
00061
00062
00063
00064 class SkewlZoneDriver : public virtual DeviceDriver, public MotionHook, public DataSource, public virtual plist::PrimitiveListener {
00065 public:
00066 static const unsigned int NUM_SERVO=NumOutputs;
00067 static const unsigned int NUM_INPUT=NumSensors;
00068 static const int UNUSED=plist::OutputSelector::UNUSED;
00069
00070
00071
00072
00073 BsLibClient_P pClient;
00074 int h;
00075 BsBotMotorPosVec_T vecMotorPos;
00076 BsBotMotorSpeedPosVec_T vecMotorMove;
00077 int index;
00078 int rc;
00079
00080
00081
00082
00083
00084 explicit SkewlZoneDriver(const std::string& name)
00085 : DeviceDriver(autoRegisterSkewlZoneDriver,name), MotionHook(), DataSource(),
00086 serialPath("/dev/ttyUSB0"), servos(NUM_SERVO,UNUSED), inputs(NUM_INPUT,UNUSED),
00087 minPW(NUM_SERVO,500), maxPW(NUM_SERVO,2500), buttonMode(NUM_INPUT,false),
00088 sparse(false), commName(), queryServos(false), poller(&SkewlZoneDriver::advance,*this,TimeET(0L),TimeET(1.0/(*sensorFramerate)),true,CallbackPollThread::IGNORE_RETURN),
00089 motionActive(false), sensorsActive(false), lastSensorTime(), frameNumber(0)
00090 {
00091 for(unsigned int i=0; i<NumOutputs && i<NUM_SERVO; ++i)
00092 servos[i]=i;
00093 for(unsigned int i=0; i<NumSensors && i<NUM_INPUT; ++i)
00094 inputs[i]=i;
00095 addEntry("SerialPath",serialPath,"Path to connect to botsense using a serial device");
00096 addEntry("OutputMap",servos,"For each of the SkewlZone's servo pins, lists the output index it should take its values from; -1 to mark unused");
00097 addEntry("InputMap",inputs,"For each of the SkewlZone's input pins, lists the sensor index it should send its value to; -1 to mark unused");
00098 addEntry("MinPulseWidth",minPW,"The low end of the servo's legal pulse width range (may correspond to unreachable position, use RobotInfo's outputRange[] to limit motion, not this)");
00099 addEntry("MaxPulseWidth",maxPW,"The high end of the servo's legal pulse width range (may correspond to unreachable position, use RobotInfo's outputRange[] to limit motion, not this)");
00100 addEntry("ButtonMode",buttonMode,"Controls interpretation of the input pin.\nFalse means directly measure voltage, true means test for high (1),\nhigh now but low was detected in interval (0.5), or low (0).\nButton mode implies interpreting inputMap value as a button index instead of sensor index.");
00101 addEntry("SparseUpdates",sparse,"If true, only send servo positions to SkewlZone when they change, instead of all servos on every update (don't use a lossy transport like UDP if you turn this on!)");
00102 addEntry("CommPort",commName,"The name of the comm port where output will be sent");
00103 addEntry("QueryServos",queryServos,"If set to true, will attempt to query the servo positions with each sensor update.\nThis may decrease the sampling frequency");
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 if(createSZclient() != SK_EC_EXEC) {
00119
00120 if(connectSZserver() != SK_EC_EXEC) {
00121
00122 if(openRCB3() != SK_EC_EXEC) {
00123
00124 attachRCB3();
00125 setSZunits();
00126 if(RCB3EStop() != SK_EC_EXEC) {
00127 printf("E Stop Applied to SkewlZone!\n");
00128 }
00129 printServos();
00130 initMotorVec();
00131 }
00132 }
00133 }
00134
00135
00136 for (unsigned int i=0; i<vecMotorPos.m_uCount; i++) {
00137 vecMotorMove.m_fBufSpeed[i] = 0.0;
00138 vecMotorMove.m_fBufPos[i] = vecMotorPos.m_fBuf[i];
00139 }
00140
00141
00142
00143
00144 }
00145 virtual ~SkewlZoneDriver() {}
00146
00147 virtual std::string getClassName() const { return autoRegisterSkewlZoneDriver; }
00148
00149 virtual MotionHook* getMotionSink() { return dynamic_cast<MotionHook*>(this); }
00150 virtual void getSensorSources(std::map<std::string,DataSource*>& sources) {
00151 sources.clear();
00152 sources["Sensors"]=dynamic_cast<DataSource*>(this);
00153 }
00154
00155 virtual void motionStarting();
00156 virtual bool isConnected();
00157 virtual void motionStopping();
00158 virtual void motionCheck(const float outputs[][NumOutputs]);
00159
00160 virtual unsigned int nextTimestamp();
00161 virtual const std::string& nextName() { return instanceName; }
00162 virtual void registerSource();
00163 virtual void deregisterSource();
00164 virtual void enteringRealtime(const plist::Primitive<double>& simTimeScale) { DataSource::enteringRealtime(simTimeScale); }
00165 virtual void leavingRealtime(bool isFullSpeed) { DataSource::leavingRealtime(isFullSpeed); }
00166 virtual bool advance();
00167
00168 virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00169
00170 plist::Primitive<std::string> serialPath;
00171 plist::ArrayOf<plist::OutputSelector> servos;
00172 plist::ArrayOf<plist::Primitive<int> > inputs;
00173 plist::ArrayOf<plist::Primitive<unsigned int> > minPW;
00174 plist::ArrayOf<plist::Primitive<unsigned int> > maxPW;
00175 plist::ArrayOf<plist::Primitive<bool> > buttonMode;
00176 plist::Primitive<bool> sparse;
00177 plist::Primitive<std::string> commName;
00178 plist::Primitive<bool> queryServos;
00179
00180
00181
00182
00183
00184 virtual void simplePrintVec(const char *sPrefix, double fBuf[], size_t uCount);
00185
00186 virtual int createSZclient();
00187
00188 virtual int connectSZserver();
00189
00190 virtual int openRCB3();
00191
00192 virtual void attachRCB3();
00193
00194 virtual int RCB3EStop();
00195
00196 virtual int convertIndex(int index);
00197
00198
00199 virtual int indexInverted(int index);
00200
00201 virtual void setSZunits();
00202
00203 virtual void printServos();
00204
00205 virtual void initMotorVec();
00206
00207
00208
00209
00210 protected:
00211 void doFreeze();
00212 void doUnfreeze();
00213
00214
00215 void provideOutput(unsigned int idx) { if(idx<NumOutputs) providingOutput(idx); }
00216
00217 void ignoreOutput(unsigned int idx) { if(idx<NumOutputs) ignoringOutput(idx); }
00218
00219
00220 virtual void setServo(std::ostream& ss, unsigned int servoIdx, float v);
00221
00222 virtual float getServo(unsigned int servoIdx, unsigned int pw);
00223
00224 virtual float getAnalog(unsigned int inputIdx, unsigned char s);
00225
00226 virtual float getDigital(unsigned int inputIdx, unsigned char cur, unsigned char latch);
00227
00228 float angleCalibration(unsigned int servoIdx, int mode, float v);
00229
00230 CallbackPollThread poller;
00231
00232
00233 bool motionActive;
00234 bool sensorsActive;
00235 unsigned int lastSensorTime;
00236 unsigned int frameNumber;
00237
00238 private:
00239
00240 static const std::string autoRegisterSkewlZoneDriver;
00241 };
00242
00243
00244
00245
00246
00247 #endif