1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
/*
INDI Developers Manual
Tutorial #2
"Simple Telescope Driver"
We develop a simple telescope simulator.
Refer to README, which contains instruction on how to build this driver, and use it
with an INDI-compatible client.
*/
/** \file simplescope.cpp
\brief Construct a basic INDI telescope device that simulates GOTO commands.
\author Jasem Mutlaq
\example simplescope.cpp
A simple GOTO telescope that simulator slewing operation.
*/
#include "simplescope.h"
#include "indicom.h"
#include <cmath>
#include <memory>
static std::unique_ptr<SimpleScope> simpleScope(new SimpleScope());
SimpleScope::SimpleScope()
{
// We add an additional debug level so we can log verbose scope status
DBG_SCOPE = INDI::Logger::getInstance().addDebugLevel("Scope Verbose", "SCOPE");
}
/**************************************************************************************
** We init our properties here. The only thing we want to init are the Debug controls
***************************************************************************************/
bool SimpleScope::initProperties()
{
// ALWAYS call initProperties() of parent first
INDI::Telescope::initProperties();
// Add Debug control so end user can turn debugging/loggin on and off
addDebugControl();
// Enable simulation mode so that serial connection in INDI::Telescope does not try
// to attempt to perform a physical connection to the serial port.
setSimulation(true);
// Set telescope capabilities. 0 is for the the number of slew rates that we support. We have none for this simple driver.
SetTelescopeCapability(TELESCOPE_CAN_GOTO | TELESCOPE_CAN_ABORT, 0);
return true;
}
/**************************************************************************************
** INDI is asking us to check communication with the device via a handshake
***************************************************************************************/
bool SimpleScope::Handshake()
{
// When communicating with a real mount, we check here if commands are receieved
// and acknolowedged by the mount. For SimpleScope, we simply return true.
return true;
}
/**************************************************************************************
** INDI is asking us for our default device name
***************************************************************************************/
const char *SimpleScope::getDefaultName()
{
return "Simple Scope";
}
/**************************************************************************************
** Client is asking us to slew to a new position
***************************************************************************************/
bool SimpleScope::Goto(double ra, double dec)
{
targetRA = ra;
targetDEC = dec;
char RAStr[64] = {0}, DecStr[64] = {0};
// Parse the RA/DEC into strings
fs_sexa(RAStr, targetRA, 2, 3600);
fs_sexa(DecStr, targetDEC, 2, 3600);
// Mark state as slewing
TrackState = SCOPE_SLEWING;
// Inform client we are slewing to a new position
LOGF_INFO("Slewing to RA: %s - DEC: %s", RAStr, DecStr);
// Success!
return true;
}
/**************************************************************************************
** Client is asking us to abort our motion
***************************************************************************************/
bool SimpleScope::Abort()
{
return true;
}
/**************************************************************************************
** Client is asking us to report telescope status
***************************************************************************************/
bool SimpleScope::ReadScopeStatus()
{
static struct timeval ltv
{
0, 0
};
struct timeval tv
{
0, 0
};
double dt = 0, da_ra = 0, da_dec = 0, dx = 0, dy = 0;
int nlocked;
/* update elapsed time since last poll, don't presume exactly POLLMS */
gettimeofday(&tv, nullptr);
if (ltv.tv_sec == 0 && ltv.tv_usec == 0)
ltv = tv;
dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6;
ltv = tv;
// Calculate how much we moved since last time
da_ra = SLEW_RATE * dt;
da_dec = SLEW_RATE * dt;
/* Process per current state. We check the state of EQUATORIAL_EOD_COORDS_REQUEST and act acoordingly */
switch (TrackState)
{
case SCOPE_SLEWING:
// Wait until we are "locked" into positon for both RA & DEC axis
nlocked = 0;
// Calculate diff in RA
dx = targetRA - currentRA;
// If diff is very small, i.e. smaller than how much we changed since last time, then we reached target RA.
if (fabs(dx) * 15. <= da_ra)
{
currentRA = targetRA;
nlocked++;
}
// Otherwise, increase RA
else if (dx > 0)
currentRA += da_ra / 15.;
// Otherwise, decrease RA
else
currentRA -= da_ra / 15.;
// Calculate diff in DEC
dy = targetDEC - currentDEC;
// If diff is very small, i.e. smaller than how much we changed since last time, then we reached target DEC.
if (fabs(dy) <= da_dec)
{
currentDEC = targetDEC;
nlocked++;
}
// Otherwise, increase DEC
else if (dy > 0)
currentDEC += da_dec;
// Otherwise, decrease DEC
else
currentDEC -= da_dec;
// Let's check if we recahed position for both RA/DEC
if (nlocked == 2)
{
// Let's set state to TRACKING
TrackState = SCOPE_TRACKING;
LOG_INFO("Telescope slew is complete. Tracking...");
}
break;
default:
break;
}
char RAStr[64] = {0}, DecStr[64] = {0};
// Parse the RA/DEC into strings
fs_sexa(RAStr, currentRA, 2, 3600);
fs_sexa(DecStr, currentDEC, 2, 3600);
DEBUGF(DBG_SCOPE, "Current RA: %s Current DEC: %s", RAStr, DecStr);
NewRaDec(currentRA, currentDEC);
return true;
}
|