00001
00002 #ifndef INCLUDED_SSC32Driver_h_
00003 #define INCLUDED_SSC32Driver_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 <iostream>
00013
00014
00015 class SSC32Driver : public virtual DeviceDriver, public MotionHook, public DataSource, public virtual plist::PrimitiveListener {
00016 public:
00017 static const unsigned int NUM_SERVO=32;
00018 static const unsigned int NUM_INPUT=4;
00019 static const int UNUSED=-1;
00020
00021 explicit SSC32Driver(const std::string& name)
00022 : DeviceDriver(autoRegisterSSC32Driver,name), MotionHook(), DataSource(),
00023 servos(NUM_SERVO,static_cast<unsigned int>(UNUSED)), inputs(NUM_INPUT,UNUSED),
00024 minPW(NUM_SERVO,500), maxPW(NUM_SERVO,2500), buttonMode(NUM_INPUT,false),
00025 sparse(false), commName(), queryServos(false), killSignalDelayed(NUM_SERVO, false), poller(&SSC32Driver::advance,*this,TimeET(0L),
00026 TimeET(1.0/(*sensorFramerate)),true,CallbackPollThread::IGNORE_RETURN),
00027 motionActive(false), sensorsActive(false), lastSensorTime(), frameNumber(0), timeLastChanged()
00028 {
00029 for(unsigned int i=0; i<NumOutputs && i<NUM_SERVO; ++i) {
00030 servos[i]=i;
00031 timeLastChanged[i] = 0;
00032 }
00033 for(unsigned int i=0; i<NumSensors && i<NUM_INPUT; ++i)
00034 inputs[i]=i;
00035 addEntry("OutputMap",servos,"For each of the SSC32's servo pins, lists the output index it should take its values from; -1 to mark unused");
00036 addEntry("InputMap",inputs,"For each of the SSC32's input pins, lists the sensor index it should send its value to; -1 to mark unused");
00037 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)");
00038 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)");
00039 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.");
00040 addEntry("SparseUpdates",sparse,"If true, only send servo positions to SSC when they change, instead of all servos on every update (don't use a lossy transport like UDP if you turn this on!)");
00041 addEntry("CommPort",commName,"The name of the comm port where output will be sent");
00042 addEntry("QueryServos",queryServos,"If set to true, will attempt to query the servo positions with each sensor update.\nThis may decrease the sampling frequency");
00043 addEntry("KillSignalDelayed", killSignalDelayed, "If set to true, the corresponding SSC output will be sent a LOW command 1 second after ceasing to change value.\n This will turn on SparseUpdates as well as QueryServos.\n");
00044 }
00045 virtual ~SSC32Driver() {}
00046
00047 virtual std::string getClassName() const { return autoRegisterSSC32Driver; }
00048
00049 virtual MotionHook* getMotionSink() { return dynamic_cast<MotionHook*>(this); }
00050 virtual void getSensorSources(std::map<std::string,DataSource*>& sources) {
00051 sources.clear();
00052 sources["Sensors"]=dynamic_cast<DataSource*>(this);
00053 }
00054
00055 virtual void motionStarting();
00056 virtual bool isConnected();
00057 virtual void motionStopping();
00058 virtual void motionCheck(const float outputs[][NumOutputs]);
00059
00060 virtual unsigned int nextTimestamp();
00061 virtual const std::string& nextName() { return instanceName; }
00062 virtual void registerSource();
00063 virtual void deregisterSource();
00064 virtual void enteringRealtime(const plist::Primitive<double>& simTimeScale) { DataSource::enteringRealtime(simTimeScale); }
00065 virtual void leavingRealtime(bool isFullSpeed) { DataSource::leavingRealtime(isFullSpeed); }
00066 virtual bool advance();
00067
00068 virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00069
00070 plist::ArrayOf<plist::OutputSelector> servos;
00071 plist::ArrayOf<plist::Primitive<int> > inputs;
00072 plist::ArrayOf<plist::Primitive<unsigned int> > minPW;
00073 plist::ArrayOf<plist::Primitive<unsigned int> > maxPW;
00074 plist::ArrayOf<plist::Primitive<bool> > buttonMode;
00075 plist::Primitive<bool> sparse;
00076 plist::Primitive<std::string> commName;
00077 plist::Primitive<bool> queryServos;
00078 plist::ArrayOf<plist::Primitive<bool> > killSignalDelayed;
00079
00080 protected:
00081 void doFreeze();
00082 void doUnfreeze();
00083
00084
00085 void provideOutput(unsigned int idx) { if(idx<NumOutputs) providingOutput(idx); }
00086
00087 void ignoreOutput(unsigned int idx) { if(idx<NumOutputs) ignoringOutput(idx); }
00088
00089
00090 virtual void setServo(std::ostream& ss, unsigned int servoIdx, float v);
00091
00092 virtual float getServo(unsigned int servoIdx, unsigned int pw);
00093
00094 virtual float getAnalog(unsigned int inputIdx, unsigned char s);
00095
00096 virtual float getDigital(unsigned int inputIdx, unsigned char cur, unsigned char latch);
00097
00098
00099
00100 CallbackPollThread poller;
00101
00102
00103 bool motionActive;
00104 bool sensorsActive;
00105 unsigned int lastSensorTime;
00106 unsigned int frameNumber;
00107 unsigned int timeLastChanged[NUM_SERVO];
00108 private:
00109
00110 static const std::string autoRegisterSSC32Driver;
00111 };
00112
00113
00114
00115
00116
00117
00118 #endif