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 "Devices/ssc.H"
00039
00040 #include "Component/OptionManager.H"
00041 #include "Devices/Serial.H"
00042
00043
00044 SSC::SSC(OptionManager& mgr, const std::string& descrName,
00045 const std::string& tagName, const char *defdev) :
00046 ModelComponent(mgr, descrName, tagName),
00047 itsPort(new Serial(mgr))
00048 {
00049
00050 itsPort->configure(defdev, 9600, "8N1", false, false, 1);
00051
00052
00053 addSubComponent(itsPort);
00054
00055
00056 zero = new rutz::shared_ptr<NModelParam<float> >[SSCNUMSERVOS];
00057 posmult = new rutz::shared_ptr<NModelParam<float> >[SSCNUMSERVOS];
00058 negmult = new rutz::shared_ptr<NModelParam<float> >[SSCNUMSERVOS];
00059 pos = new byte[SSCNUMSERVOS];
00060 for (uint i = 0; i < SSCNUMSERVOS; i ++)
00061 {
00062 pos[i] = 127; char buf[20];
00063
00064 sprintf(buf, "Zero%d", i);
00065 zero[i] = NModelParam<float>::make(buf, this, 0.0F);
00066
00067 sprintf(buf, "PosMult%d", i);
00068 posmult[i] = NModelParam<float>::make(buf, this, 1.0F);
00069
00070 sprintf(buf, "NegMult%d", i);
00071 negmult[i] = NModelParam<float>::make(buf, this, 1.0F);
00072 }
00073 }
00074
00075
00076 SSC::~SSC()
00077 { }
00078
00079
00080 bool SSC::move(const int servo, const float position)
00081 { return moveRaw(servo, calibToRaw(servo, position)); }
00082
00083
00084 float SSC::getPosition(const int servo) const
00085 {
00086 if (servo < 0 || servo >= SSCNUMSERVOS)
00087 LFATAL("Invalid servo number %d", servo);
00088 return rawToCalib(servo, pos[servo]);
00089 }
00090
00091
00092 void SSC::calibrate(const int servo, const byte neutralval, const byte minval,
00093 const byte maxval)
00094 {
00095 if (servo < 0 || servo >= SSCNUMSERVOS)
00096 LFATAL("Invalid servo number %d", servo);
00097
00098 zero[servo]->setVal(float(neutralval));
00099 negmult[servo]->setVal(1.0F / (float(neutralval) - float(minval)));
00100 posmult[servo]->setVal(1.0F / (float(maxval) - float(neutralval)));
00101 }
00102
00103
00104 bool SSC::moveRaw(const int servo, const byte rawpos)
00105 {
00106
00107
00108
00109
00110 char command[3];
00111 command[0] = 255;
00112 command[1] = servo;
00113 command[2] = rawpos;
00114
00115
00116 if (itsPort->write(command, 3) == 3)
00117 {
00118
00119 pos[servo] = rawpos;
00120 return true;
00121 }
00122 else
00123 return false;
00124 }
00125
00126
00127 bool SSC::moveRawHack(const int servo, const byte rawpos, const int port)
00128 {
00129
00130
00131
00132
00133 char command[3];
00134 command[0] = 255;
00135 command[1] = servo;
00136 command[2] = rawpos;
00137 int fd;
00138 if(port == 1)
00139 fd = open("/dev/ttyS0", O_RDWR);
00140 else
00141 fd = open("/dev/ttyS1", O_RDWR);
00142 if(fd==-1) LFATAL("open failed");
00143 if(write(fd, command, 3)==-1){
00144 perror("open");
00145 LFATAL("write failed");
00146 }
00147 close(fd);
00148 return true;
00149 }
00150
00151
00152 byte SSC::getPositionRaw(const int servo) const
00153 {
00154 if (servo < 0 || servo >= SSCNUMSERVOS)
00155 LFATAL("Invalid servo number %d", servo);
00156
00157 return pos[servo];
00158 }
00159
00160
00161 float SSC::rawToCalib(const int servo, const byte rawpos) const
00162 {
00163 if (servo < 0 || servo >= SSCNUMSERVOS)
00164 LFATAL("Invalid servo number %d", servo);
00165
00166 float position;
00167 if (rawpos >= byte(zero[servo]->getVal()))
00168 position = (float(rawpos) - zero[servo]->getVal()) *
00169 posmult[servo]->getVal();
00170 else
00171 position = (float(rawpos) - zero[servo]->getVal()) *
00172 negmult[servo]->getVal();
00173
00174 if (position < -1.0F) position = -1.0F;
00175 else if (position > 1.0F) position = 1.0F;
00176
00177 return position;
00178 }
00179
00180
00181 byte SSC::calibToRaw(const int servo, const float position) const
00182 {
00183 if (servo < 0 || servo >= SSCNUMSERVOS)
00184 LFATAL("Invalid servo number %d", servo);
00185
00186 if (position > 1.0F || position < -1.0F)
00187 LFATAL("Invalid position %f (range -1.0..1.0)", position);
00188
00189 int rawpos;
00190 if (position < 0.0F)
00191 rawpos = int(position / negmult[servo]->getVal() +
00192 zero[servo]->getVal() + 0.49999F);
00193 else
00194 rawpos = int(position / posmult[servo]->getVal() +
00195 zero[servo]->getVal() + 0.49999F);
00196
00197 if (rawpos < 0) rawpos = 0; else if (rawpos > 255) rawpos = 255;
00198
00199 return byte(rawpos);
00200 }
00201
00202
00203
00204
00205
00206