- Timestamp:
- Feb 24, 2012, 12:37:36 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
BAORadio/libindi/libindi/drivers/telescope/telescope_simulator.cpp
r504 r642 13 13 std::auto_ptr<ScopeSim> telescope_sim(0); 14 14 15 #define SLEWRATE 1 /* slew rate, degrees/s */ 15 #define GOTO_RATE 2 /* slew rate, degrees/s */ 16 #define SLEW_RATE 0.5 /* slew rate, degrees/s */ 17 #define FINE_SLEW_RATE 0.1 /* slew rate, degrees/s */ 18 #define SID_RATE 0.004178 /* sidereal rate, degrees/s */ 19 20 #define GOTO_LIMIT 5 /* Move at GOTO_RATE until distance from target is GOTO_LIMIT degrees */ 21 #define SLEW_LIMIT 2 /* Move at SLEW_LIMIT until distance from target is SLEW_LIMIT degrees */ 22 #define FINE_SLEW_LIMIT 0.5 /* Move at FINE_SLEW_RATE until distance from target is FINE_SLEW_LIMIT degrees */ 23 16 24 #define POLLMS 250 /* poll period, ms */ 17 #define SIDRATE 0.004178 /* sidereal rate, degrees/s */ 25 26 #define RA_AXIS 0 27 #define DEC_AXIS 1 28 #define GUIDE_NORTH 0 29 #define GUIDE_SOUTH 1 30 #define GUIDE_WEST 0 31 #define GUIDE_EAST 1 32 18 33 19 34 … … 80 95 currentDEC=15; 81 96 Parked=false; 97 98 GuideNSNP = new INumberVectorProperty; 99 GuideWENP = new INumberVectorProperty; 100 EqPECNV = new INumberVectorProperty; 101 GuideRateNP = new INumberVectorProperty; 102 103 PECErrNSSP = new ISwitchVectorProperty; 104 PECErrWESP = new ISwitchVectorProperty; 105 106 /* initialize random seed: */ 107 srand ( time(NULL) ); 82 108 } 83 109 … … 90 116 { 91 117 return (char *)"Telescope Simulator"; 118 } 119 120 bool ScopeSim::initProperties() 121 { 122 /* Make sure to init parent properties first */ 123 INDI::Telescope::initProperties(); 124 125 /* Property for guider support. How many seconds to guide either northward or southward? */ 126 IUFillNumber(&GuideNSN[GUIDE_NORTH], "TIMED_GUIDE_N", "North (sec)", "%g", 0, 10, 0.001, 0); 127 IUFillNumber(&GuideNSN[GUIDE_SOUTH], "TIMED_GUIDE_S", "South (sec)", "%g", 0, 10, 0.001, 0); 128 IUFillNumberVector(GuideNSNP, GuideNSN, 2, deviceName(), "TELESCOPE_TIMED_GUIDE_NS", "Guide North/South", MOTION_TAB, IP_RW, 0, IPS_IDLE); 129 130 /* Property for guider support. How many seconds to guide either westward or eastward? */ 131 IUFillNumber(&GuideWEN[GUIDE_WEST], "TIMED_GUIDE_W", "West (sec)", "%g", 0, 10, 0.001, 0); 132 IUFillNumber(&GuideWEN[GUIDE_EAST], "TIMED_GUIDE_E", "East (sec)", "%g", 0, 10, 0.001, 0); 133 IUFillNumberVector(GuideWENP, GuideWEN, 2, deviceName(), "TELESCOPE_TIMED_GUIDE_WE", "Guide West/East", MOTION_TAB, IP_RW, 0, IPS_IDLE); 134 135 /* Simulated periodic error in RA, DEC */ 136 IUFillNumber(&EqPECN[RA_AXIS],"RA_PEC","RA (hh:mm:ss)","%010.6m",0,24,0,15.); 137 IUFillNumber(&EqPECN[DEC_AXIS],"DEC_PEC","DEC (dd:mm:ss)","%010.6m",-90,90,0,15.); 138 IUFillNumberVector(EqPECNV,EqPECN,2,deviceName(),"EQUATORIAL_PEC","Periodic Error",MOTION_TAB,IP_RO,60,IPS_IDLE); 139 140 /* Enable client to manually add periodic error northward or southward for simulation purposes */ 141 IUFillSwitch(&PECErrNSS[MOTION_NORTH], "PEC_N", "North", ISS_OFF); 142 IUFillSwitch(&PECErrNSS[MOTION_SOUTH], "PEC_S", "South", ISS_OFF); 143 IUFillSwitchVector(PECErrNSSP, PECErrNSS, 2, deviceName(),"PEC_NS", "PE N/S", MOTION_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); 144 145 /* Enable client to manually add periodic error westward or easthward for simulation purposes */ 146 IUFillSwitch(&PECErrWES[MOTION_WEST], "PEC_W", "West", ISS_OFF); 147 IUFillSwitch(&PECErrWES[MOTION_EAST], "PEC_E", "East", ISS_OFF); 148 IUFillSwitchVector(PECErrWESP, PECErrWES, 2, deviceName(),"PEC_WE", "PE W/E", MOTION_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE); 149 150 /* How fast do we guide compared to sideral rate */ 151 IUFillNumber(&GuideRateN[RA_AXIS], "GUIDE_RATE_WE", "W/E Rate", "%g", 0, 1, 0.1, 0.3); 152 IUFillNumber(&GuideRateN[DEC_AXIS], "GUIDE_RATE_NS", "N/S Rate", "%g", 0, 1, 0.1, 0.3); 153 IUFillNumberVector(GuideRateNP, GuideRateN, 2, deviceName(), "GUIDE_RATE", "Guiding Rate", MOTION_TAB, IP_RW, 0, IPS_IDLE); 154 155 /* Add debug controls so we may debug driver if necessary */ 156 addDebugControl(); 157 158 return true; 159 } 160 161 void ScopeSim::ISGetProperties (const char *dev) 162 { 163 /* First we let our parent populate */ 164 INDI::Telescope::ISGetProperties(dev); 165 166 if(isConnected()) 167 { 168 defineNumber(GuideNSNP); 169 defineNumber(GuideWENP); 170 defineNumber(GuideRateNP); 171 defineNumber(EqPECNV); 172 defineSwitch(PECErrNSSP); 173 defineSwitch(PECErrWESP); 174 } 175 176 return; 177 } 178 179 bool ScopeSim::updateProperties() 180 { 181 INDI::Telescope::updateProperties(); 182 183 if (isConnected()) 184 { 185 defineNumber(GuideNSNP); 186 defineNumber(GuideWENP); 187 defineNumber(GuideRateNP); 188 defineNumber(EqPECNV); 189 defineSwitch(PECErrNSSP); 190 defineSwitch(PECErrWESP); 191 192 } 193 else 194 { 195 deleteProperty(GuideNSNP->name); 196 deleteProperty(GuideWENP->name); 197 deleteProperty(EqPECNV->name); 198 deleteProperty(PECErrNSSP->name); 199 deleteProperty(PECErrNSSP->name); 200 deleteProperty(GuideRateNP->name); 201 } 202 203 return true; 204 } 205 206 bool ScopeSim::Connect() 207 { 208 bool rc=false; 209 210 if(isConnected()) return true; 211 212 rc=Connect(PortT[0].text); 213 214 if(rc) 215 SetTimer(POLLMS); 216 217 return rc; 92 218 } 93 219 … … 106 232 static struct timeval ltv; 107 233 struct timeval tv; 108 double dt, da, dx; 109 int nlocked; 234 double dt=0, da_ra=0, da_dec=0, dx=0, dy=0, ra_guide_dt=0, dec_guide_dt=0; 235 static double last_dx=0, last_dy=0; 236 int nlocked, ns_guide_dir=-1, we_guide_dir=-1; 237 char RA_DISP[64], DEC_DISP[64], RA_GUIDE[64], DEC_GUIDE[64], RA_PEC[64], DEC_PEC[64], RA_TARGET[64], DEC_TARGET[64]; 110 238 111 239 … … 118 246 dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec)/1e6; 119 247 ltv = tv; 120 da = SLEWRATE*dt; 248 249 if ( fabs(targetRA - currentRA)*15. >= GOTO_LIMIT ) 250 da_ra = GOTO_RATE *dt; 251 else if ( fabs(targetRA - currentRA)*15. >= SLEW_LIMIT ) 252 da_ra = SLEW_RATE *dt; 253 else 254 da_ra = FINE_SLEW_RATE *dt; 255 256 if ( fabs(targetDEC - currentDEC) >= GOTO_LIMIT ) 257 da_dec = GOTO_RATE *dt; 258 else if ( fabs(targetDEC - currentDEC) >= SLEW_LIMIT ) 259 da_dec = SLEW_RATE *dt; 260 else 261 da_dec = FINE_SLEW_RATE *dt; 262 263 switch (MovementNSSP->s) 264 { 265 case IPS_BUSY: 266 if (MovementNSS[MOTION_NORTH].s == ISS_ON) 267 currentDEC += da_dec; 268 else if (MovementNSS[MOTION_SOUTH].s == ISS_ON) 269 currentDEC -= da_dec; 270 271 NewRaDec(currentRA, currentDEC); 272 return true; 273 break; 274 } 275 276 switch (MovementWESP->s) 277 { 278 case IPS_BUSY: 279 280 if (MovementWES[MOTION_WEST].s == ISS_ON) 281 currentRA += da_ra/15.; 282 else if (MovementWES[MOTION_EAST].s == ISS_ON) 283 currentRA -= da_ra/15.; 284 285 NewRaDec(currentRA, currentDEC); 286 return true; 287 break; 288 289 } 121 290 122 291 /* Process per current state. We check the state of EQUATORIAL_EOD_COORDS_REQUEST and act acoordingly */ 123 292 switch (TrackState) 124 293 { 294 case SCOPE_IDLE: 295 EqNV->s = IPS_IDLE; 296 break; 125 297 case SCOPE_SLEWING: 126 298 case SCOPE_PARKING: … … 130 302 dx = targetRA - currentRA; 131 303 132 if (fabs(dx) <= da)304 if (fabs(dx)*15. <= da_ra) 133 305 { 134 306 currentRA = targetRA; … … 136 308 } 137 309 else if (dx > 0) 138 currentRA += da /15.;310 currentRA += da_ra/15.; 139 311 else 140 currentRA -= da /15.;141 142 143 d x= targetDEC - currentDEC;144 if (fabs(d x) <= da)312 currentRA -= da_ra/15.; 313 314 315 dy = targetDEC - currentDEC; 316 if (fabs(dy) <= da_dec) 145 317 { 146 318 currentDEC = targetDEC; 147 319 nlocked++; 148 320 } 149 else if (d x> 0)150 currentDEC += da ;321 else if (dy > 0) 322 currentDEC += da_dec; 151 323 else 152 currentDEC -= da; 324 currentDEC -= da_dec; 325 326 EqNV->s = IPS_BUSY; 153 327 154 328 if (nlocked == 2) 155 329 { 156 //eqNP.s = IPS_OK;157 //eqNPR.s = IPS_OK;158 //IDSetNumber(&eqNP, NULL);159 //IDSetNumber(&eqNPR, "Now tracking");160 330 if (TrackState == SCOPE_SLEWING) 161 331 { 332 333 // Initially no PEC in both axis. 334 EqPECN[0].value = currentRA; 335 EqPECN[1].value = currentDEC; 336 337 IDSetNumber(EqPECNV, NULL); 338 162 339 TrackState = SCOPE_TRACKING; 340 341 EqNV->s = IPS_OK; 163 342 IDMessage(deviceName(), "Telescope slew is complete. Tracking..."); 164 343 } … … 166 345 { 167 346 TrackState = SCOPE_PARKED; 347 EqNV->s = IPS_IDLE; 168 348 IDMessage(deviceName(), "Telescope parked successfully."); 169 349 } 170 350 } 171 //else172 // IDSetNumber(&eqNP, NULL);173 351 174 352 break; … … 176 354 case SCOPE_TRACKING: 177 355 /* tracking */ 178 /* RA moves at sidereal, Dec stands still */ 179 currentRA += (SIDRATE*dt/15.); 356 357 if (GuideNSN[GUIDE_NORTH].value > 0) 358 { 359 if (isDebug()) 360 IDLog(" ****** Commanded to GUIDE NORTH for %g ms *****\n", GuideNSN[GUIDE_NORTH].value*1000); 361 ns_guide_dir = GUIDE_NORTH; 362 } 363 else if (GuideNSN[GUIDE_SOUTH].value > 0) 364 { 365 if (isDebug()) 366 IDLog(" ****** Commanded to GUIDE SOUTH for %g ms *****\n", GuideNSN[GUIDE_SOUTH].value*1000); 367 ns_guide_dir = GUIDE_SOUTH; 368 } 369 370 // WE Guide Selection 371 if (GuideWEN[GUIDE_WEST].value > 0) 372 { 373 we_guide_dir = GUIDE_WEST; 374 if (isDebug()) 375 IDLog(" ****** Commanded to GUIDE WEST for %g ms ****** \n", GuideWEN[GUIDE_WEST].value*1000); 376 } 377 else if (GuideWEN[GUIDE_EAST].value > 0) 378 { 379 we_guide_dir = GUIDE_EAST; 380 if (isDebug()) 381 IDLog(" ****** Commanded to GUIDE EAST for %g ms ****** \n", GuideWEN[GUIDE_EAST].value*1000); 382 } 383 384 if (ns_guide_dir != -1) 385 { 386 387 dec_guide_dt = SID_RATE * GuideRateN[DEC_AXIS].value * GuideNSN[ns_guide_dir].value * (ns_guide_dir==GUIDE_NORTH ? 1 : -1); 388 389 // If time remaining is more that dt, then decrement and 390 if (GuideNSN[ns_guide_dir].value >= dt) 391 GuideNSN[ns_guide_dir].value -= dt; 392 else 393 GuideNSN[ns_guide_dir].value = 0; 394 395 EqPECN[DEC_AXIS].value += dec_guide_dt; 396 397 if (GuideNSN[ns_guide_dir].value <= 0) 398 { 399 GuideNSN[GUIDE_NORTH].value = GuideNSN[GUIDE_SOUTH].value = 0; 400 GuideNSNP->s = IPS_OK; 401 IDSetNumber(GuideNSNP, NULL); 402 } 403 else 404 IDSetNumber(GuideNSNP, NULL); 405 } 406 407 if (we_guide_dir != -1) 408 { 409 410 ra_guide_dt = SID_RATE/15.0 * GuideRateN[RA_AXIS].value * GuideWEN[we_guide_dir].value* (we_guide_dir==GUIDE_WEST ? -1 : 1); 411 412 if (GuideWEN[we_guide_dir].value >= dt) 413 GuideWEN[we_guide_dir].value -= dt; 414 else 415 GuideWEN[we_guide_dir].value = 0; 416 417 EqPECN[RA_AXIS].value += ra_guide_dt; 418 419 if (GuideWEN[we_guide_dir].value <= 0) 420 { 421 GuideWEN[GUIDE_WEST].value = GuideWEN[GUIDE_EAST].value = 0; 422 GuideWENP->s = IPS_OK; 423 IDSetNumber(GuideWENP, NULL); 424 } 425 else 426 IDSetNumber(GuideWENP, NULL); 427 } 428 429 430 //Mention the followng: 431 // Current RA displacemet and direction 432 // Current DEC displacement and direction 433 // Amount of RA GUIDING correction and direction 434 // Amount of DEC GUIDING correction and direction 435 436 dx = EqPECN[RA_AXIS].value - targetRA; 437 dy = EqPECN[DEC_AXIS].value - targetDEC; 438 fs_sexa(RA_DISP, fabs(dx), 2, 3600 ); 439 fs_sexa(DEC_DISP, fabs(dy), 2, 3600 ); 440 441 fs_sexa(RA_GUIDE, fabs(ra_guide_dt), 2, 3600 ); 442 fs_sexa(DEC_GUIDE, fabs(dec_guide_dt), 2, 3600 ); 443 444 fs_sexa(RA_PEC, EqPECN[RA_AXIS].value, 2, 3600); 445 fs_sexa(DEC_PEC, EqPECN[DEC_AXIS].value, 2, 3600); 446 447 fs_sexa(RA_TARGET, targetRA, 2, 3600); 448 fs_sexa(DEC_TARGET, targetDEC, 2, 3600); 449 450 451 if (isDebug() && (dx!=last_dx || dy!=last_dy || ra_guide_dt || dec_guide_dt)) 452 { 453 last_dx=dx; 454 last_dy=dy; 455 IDLog("#########################################\n"); 456 IDLog("dt is %g\n", dt); 457 IDLog("RA Displacement (%c%s) %s -- %s of target RA %s\n", dx >= 0 ? '+' : '-', RA_DISP, RA_PEC, (EqPECN[RA_AXIS].value - targetRA) > 0 ? "East" : "West", RA_TARGET); 458 IDLog("DEC Displacement (%c%s) %s -- %s of target RA %s\n", dy >= 0 ? '+' : '-', DEC_DISP, DEC_PEC, (EqPECN[DEC_AXIS].value - targetDEC) > 0 ? "North" : "South", DEC_TARGET); 459 IDLog("RA Guide Correction (%g) %s -- Direction %s\n", ra_guide_dt, RA_GUIDE, ra_guide_dt > 0 ? "East" : "West"); 460 IDLog("DEC Guide Correction (%g) %s -- Direction %s\n", dec_guide_dt, DEC_GUIDE, dec_guide_dt > 0 ? "North" : "South"); 461 IDLog("#########################################\n"); 462 } 463 464 if (ns_guide_dir != -1 || we_guide_dir != -1) 465 IDSetNumber(EqPECNV, NULL); 466 180 467 break; 181 468 … … 200 487 Parked=false; 201 488 TrackState = SCOPE_SLEWING; 489 490 EqReqNV->s = IPS_BUSY; 491 EqNV->s = IPS_BUSY; 492 202 493 IDMessage(deviceName(), "Slewing to RA: %s - DEC: %s", RAStr, DecStr); 203 494 return true; … … 214 505 } 215 506 216 bool ScopeSim::Connect() 217 { 218 // Parent class is wanting a connection 219 //IDLog("INDI::Telescope calling connect with %s\n",PortT[0].text); 220 bool rc=false; 221 222 if(isConnected()) return true; 223 224 //IDLog("Calling Connect\n"); 225 226 rc=Connect(PortT[0].text); 227 228 if(rc) 229 SetTimer(POLLMS); 230 return rc; 231 } 232 233 234 235 /* update the "mount" over time */ 236 void mountSim (void *p) 237 { 238 239 } 240 241 507 bool ScopeSim::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n) 508 { 509 // first check if it's for our device 510 511 if(strcmp(dev,deviceName())==0) 512 { 513 // This is for our device 514 // Now lets see if it's something we process here 515 if(strcmp(name,"TELESCOPE_TIMED_GUIDE_NS")==0) 516 { 517 518 // Unless we're in track mode, we don't obey guide commands. 519 if (TrackState != SCOPE_TRACKING) 520 { 521 GuideNSNP->s = IPS_IDLE; 522 IDSetNumber(GuideNSNP, NULL); 523 return true; 524 } 525 526 IUUpdateNumber(GuideNSNP, values, names, n); 527 528 return true; 529 } 530 531 if(strcmp(name,"TELESCOPE_TIMED_GUIDE_WE")==0) 532 { 533 // Unless we're in track mode, we don't obey guide commands. 534 if (TrackState != SCOPE_TRACKING) 535 { 536 GuideWENP->s = IPS_IDLE; 537 IDSetNumber(GuideWENP, NULL); 538 return true; 539 } 540 541 IUUpdateNumber(GuideWENP, values, names, n); 542 543 return true; 544 } 545 546 if(strcmp(name,"GUIDE_RATE")==0) 547 { 548 IUUpdateNumber(GuideRateNP, values, names, n); 549 GuideRateNP->s = IPS_OK; 550 IDSetNumber(GuideRateNP, NULL); 551 return true; 552 } 553 554 } 555 556 // if we didn't process it, continue up the chain, let somebody else 557 // give it a shot 558 return INDI::Telescope::ISNewNumber(dev,name,values,names,n); 559 } 560 561 bool ScopeSim::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n) 562 { 563 //IDLog("Enter IsNewSwitch for %s\n",name); 564 //for(int x=0; x<n; x++) { 565 // IDLog("Switch %s %d\n",names[x],states[x]); 566 //} 567 568 if(strcmp(dev,deviceName())==0) 569 { 570 if(strcmp(name,"PEC_NS")==0) 571 { 572 IUUpdateSwitch(PECErrNSSP,states,names,n); 573 574 PECErrNSSP->s = IPS_OK; 575 576 if (PECErrNSS[MOTION_NORTH].s == ISS_ON) 577 { 578 EqPECN[DEC_AXIS].value += SID_RATE * GuideRateN[DEC_AXIS].value; 579 if (isDebug()) 580 IDLog("$$$$$ Simulating PE in NORTH direction for value of %g $$$$$\n", SID_RATE); 581 } 582 else 583 { 584 EqPECN[DEC_AXIS].value -= SID_RATE * GuideRateN[DEC_AXIS].value; 585 if (isDebug()) 586 IDLog("$$$$$ Simulating PE in SOUTH direction for value of %g $$$$$\n", SID_RATE); 587 } 588 589 IUResetSwitch(PECErrNSSP); 590 IDSetSwitch(PECErrNSSP, NULL); 591 IDSetNumber(EqPECNV, NULL); 592 593 return true; 594 595 } 596 597 if(strcmp(name,"PEC_WE")==0) 598 { 599 IUUpdateSwitch(PECErrWESP,states,names,n); 600 601 PECErrWESP->s = IPS_OK; 602 603 if (PECErrWES[MOTION_WEST].s == ISS_ON) 604 { 605 EqPECN[RA_AXIS].value -= SID_RATE/15. * GuideRateN[RA_AXIS].value; 606 if (isDebug()) 607 IDLog("$$$$$ Simulator PE in WEST direction for value of %g $$$$$$\n", SID_RATE); 608 } 609 else 610 { 611 EqPECN[RA_AXIS].value += SID_RATE/15. * GuideRateN[RA_AXIS].value; 612 if (isDebug()) 613 IDLog("$$$$$$ Simulator PE in EAST direction for value of %g $$$$$$\n", SID_RATE); 614 } 615 616 IUResetSwitch(PECErrWESP); 617 IDSetSwitch(PECErrWESP, NULL); 618 IDSetNumber(EqPECNV, NULL); 619 620 return true; 621 622 } 623 624 } 625 626 // Nobody has claimed this, so, ignore it 627 return INDI::Telescope::ISNewSwitch(dev,name,states,names,n); 628 } 629 630 631 632 bool ScopeSim::MoveNS(TelescopeMotionNS dir) 633 { 634 static int last_motion=-1; 635 636 switch (dir) 637 { 638 case MOTION_NORTH: 639 if (last_motion != MOTION_NORTH) 640 last_motion = MOTION_NORTH; 641 else 642 { 643 IUResetSwitch(MovementNSSP); 644 MovementNSSP->s = IPS_IDLE; 645 IDSetSwitch(MovementNSSP, NULL); 646 } 647 break; 648 649 case MOTION_SOUTH: 650 if (last_motion != MOTION_SOUTH) 651 last_motion = MOTION_SOUTH; 652 else 653 { 654 IUResetSwitch(MovementNSSP); 655 MovementNSSP->s = IPS_IDLE; 656 IDSetSwitch(MovementNSSP, NULL); 657 } 658 break; 659 } 660 661 return true; 662 } 663 664 bool ScopeSim::MoveWE(TelescopeMotionWE dir) 665 { 666 static int last_motion=-1; 667 668 switch (dir) 669 { 670 case MOTION_WEST: 671 if (last_motion != MOTION_WEST) 672 last_motion = MOTION_WEST; 673 else 674 { 675 IUResetSwitch(MovementWESP); 676 MovementWESP->s = IPS_IDLE; 677 IDSetSwitch(MovementWESP, NULL); 678 } 679 break; 680 681 case MOTION_EAST: 682 if (last_motion != MOTION_EAST) 683 last_motion = MOTION_EAST; 684 else 685 { 686 IUResetSwitch(MovementWESP); 687 MovementWESP->s = IPS_IDLE; 688 IDSetSwitch(MovementWESP, NULL); 689 } 690 break; 691 } 692 693 return true; 694 695 } 696
Note: See TracChangeset
for help on using the changeset viewer.