I’ve been long waiting for sharing SkyPlanner source code in a public repository.

Problem is, I had to fix a few copyright headers, cleanup some stuff, and, you know, laziness.

Now I finally published them on my GitHub account: https://github.com/GuLinux/SkyPlanner.

It’s still missing a README file for compiling and all, but if someone is curious about how SkyPlanner works, this is a huge start for poking it.

Happy hacking!

Continue reading...

When programming in C++ it can often happen to be using C-style API.
These usually come in the form:

int some_api_call(char *inputParameter, char **outputParameter);

where the return value is never a real output value, but instead an exit code, and usually 0 means success.

To handle such API in a sequence of operations, one is then usually blinded to do something like this:

 int result = first_c_api_call();
 if(result != 0) {
 cerr << "Error executing first_c_api_call: " << result << endl;
 return;
 }

result = second_c_api_call();
if(result != 0) {
cerr << "Error executing second_c_api_call: " << result << endl;
return;
}

result = third_c_api_call();
.....

and so on, which is kinda boring when you have to call lots of API functions in one method.

I have been trying to write some kind of wrapper that can help making this a bit easier.
In a real life example, I’ve been trying to use gphoto2 api in a c++11 application.
Using c++11 lambdas and RAII this is what I’ve been able to do:

 void GPhotoCamera::connect() {
      CameraAbilities abilities;
      GPPortInfo portInfo;
      CameraAbilitiesList *abilities_list = nullptr;
      GPPortInfoList *portInfoList = nullptr;
      CameraText camera_summary;
      CameraText camera_about;
      int model, port;
      gp_api{{
        sequence_run( [&]{ return gp_abilities_list_new (&abilities_list); } ),
        sequence_run( [&]{ return gp_abilities_list_load(abilities_list, d->context); } ),
        sequence_run( [&]{ model = gp_abilities_list_lookup_model(abilities_list, d->model.toLocal8Bit()); return model; } ),
        sequence_run( [&]{ return gp_abilities_list_get_abilities(abilities_list, model, &abilities); } ),
        sequence_run( [&]{ return gp_camera_set_abilities(d->camera, abilities); } ),
        sequence_run( [&]{ return gp_port_info_list_new(&portInfoList); } ),
        sequence_run( [&]{ return gp_port_info_list_load(portInfoList); } ),
        sequence_run( [&]{ return gp_port_info_list_count(portInfoList); } ),
        sequence_run( [&]{ port = gp_port_info_list_lookup_path(portInfoList, d->port.c_str()); return port; } ),
        sequence_run( [&]{ return gp_port_info_list_get_info(portInfoList, port, &portInfo); return port; } ),
        sequence_run( [&]{ return gp_camera_set_port_info(d->camera, portInfo); } ),
        sequence_run( [&]{ return gp_camera_get_summary(d->camera, &camera_summary, d->context); } ),
        sequence_run( [&]{ return gp_camera_get_about(d->camera, &camera_about, d->context); } ),
      }, make_shared<QMutexLocker>(&d->mutex)}
      .on_error([=](int errorCode, const std::string &label) {
        qDebug() << "on " << label << ": " << gphoto_error(errorCode);
        emit error(this, gphoto_error(errorCode));
      }).run_last([&]{
        d->summary = QString(camera_summary.text);
        d->about = QString(camera_about.text);
        emit connected();    
      });  
      // TODO d->reloadSettings();
      gp_port_info_list_free(portInfoList);
      gp_abilities_list_free(abilities_list);
}

I can then declare some variables in the first part of the method, and inside the “gp_api” block i can execute a sequence of operation, each one returning an int value. This value is automatically checked for an error, and if it it’s a success exit code, the next sequence block is executed.
run_last is finally executed if all steps are completed successfully. An optional mutex locker (QMutexLocker) is passed to the gp_api block as the last constructor argument, to automatically lock the c api for multithreading.

How have I accomplished this?

This is the main class so far:

#include <functional>
#include <list>
#include <mutex>

typedef std::shared_ptr<std::unique_lock<std::mutex>> default_lock;
template<typename T, T defaultValue, typename check_operator = std::equal_to<T>, typename RAII_Object = default_lock>
class sequence {
public:
  typedef std::function<T()> run_function;
  typedef std::function<void(const T &, const std::string &)> on_error_f;
  struct run {
    run_function f;
    std::string label;
    T check;
    run(run_function f, const std::string &label = {}, T check = defaultValue) : f(f), label(label), check(check) {}
  };
  sequence(const std::list<run> &runs, const RAII_Object &raii_object = {}) : runs(runs), _check_operator(check_operator{}), raii_object(raii_object) {}
  ~sequence() {
    for(auto r: runs) {
      T result = r.f();
      if(! _check_operator(result, r.check)) {
    _run_on_error(result, r.label);
    return;
      }
    };
    _run_last();
  }
  sequence &on_error(on_error_f run_on_error) { _run_on_error = run_on_error; return *this; }
  sequence &run_last(std::function<void()> run_last) { _run_last = run_last; return *this; }
  sequence &add(run r) { runs.push_back(r); }
private:
  std::list<run> runs;
  on_error_f _run_on_error = [](const T&, const std::string&) {};
  check_operator _check_operator;
  std::function<void()> _run_last = []{};
  RAII_Object raii_object;
};
#define sequence_run(...) { __VA_ARGS__ , #__VA_ARGS__}

The sequence class accepts a list of runs as construction parameters. These are stored as a class field, and sequentially executed at class destruction.
Sequence is a template class: you can define the return value type, the success value, a comparison operator to check each function result code against the success value, and finally a generic RAII_Object, which can be as previously told a mutex locker, or some other kind of resource to unlock after API executions.

The define directive at the end of the code is used to automatically create a run object which already contains a description of the code being executed (stringified).
You get this description in the on_error callback.

Near my gphoto class I also added a typedef to conveniently call the proper sequence template class with correct template parameters:

typedef sequence<int, GP_OK, std::greater_equal<int>, std::shared_ptr<QMutexLocker>> gp_api;

Which means that gp_api accepts code blocks returning int values, that the “ok” value is GP_OK (0), and that the returned value must be equal or greater than GP_OK to be considered a success run.
It also accepts a QMutexLocker shared pointer for thread locking.
As you can see in my first example I didn’t assign the gp_api object to any variable; this means that it is immediatly created, executed and destructed, for synchronous run.

So this is a simplified usage example:

gp_api{{
  sequence_run([&]{ return first_c_api_call(); }),
  sequence_run([&]{ return second_c_api_call(); }),
}, std::make_shared<QMutexLocker>(&&;mutex)}
  .on_error([=](int errorCode, const std::string &label) {
      std::cerr << "Error at code block " << label << ": " << errorCode << std::endl;
    })
  .run_last([&]{
    // run when everything runned smoothly
  });

Continue reading...

Visto che proprio questo fine settimana l’ho un po’ “ristrutturato”, ne approfitto per presentarvi il mio server:

Zerogoki
Zerogoki

Si tratta di un vecchio notebook, con cpu Intel Core 2 Duo a 2,5 Ghz, con 4 GB di RAM.
E’ solo un server domestico quindi, ma con un bel po’ di servizi sopra: il blog/sito wordpress che state vedendo adesso, SkyPlanner, un media center web sviluppato da me, e una serie di servizi interni (ssh, database, file server).

La connessione ad internet è su fibra ottica, 100 Mbit in download, 10 in upload.

Il recente “restyling” è consistito nel togliere completamente la scheda madre dall’involucro “stipato” tipico dei portatili, in modo da far respirare un po’ di più le componenti (la temperatura è drasticamente calata, difatti). Ho anche tolto alcune componenti inutili, come il lettore dvd o la scheda di rete wireless e il bluetooth, in modo da ridurre anche i consumi.

La batteria originale del notebook è invece ancora lì, molto utile durante eventuali cali o interruzioni di tensione, per mantenere il server up and running.

Continue reading...

A shot at the moon taken in a last quarter evening.

It’s a mosaic of 78 pictures, each of them stacked from 300 frames of 500. Images were taken at primary focus of my Meade ACF 8″ (2000 mm focal length), using a QHY5II-L mono.

Moon Mosaic - September 2014

Seeing was a bit too bad (I have to shoot from my window, since I don’t have a garden, which can make turbulence even worse).

Even if it’s not a perfect result I’m pretty satisfied: given the conditions lots of details are visible, and it also look quite good.
I hope to be able to shoot something even better soon 🙂

Continue reading...

Notice: this article is currently available in italian only.
I will translate it soon. You may contact me via comments if you want me to “prioritize” this article first.

Altre riprese delle macchie solari, in una giornata in cui la nostra stella era particolarmente ricca di dettagli.
In questo caso, essendoci parecchie macchie a fare da punti di riferimento, sono riuscito a fare un buon numero di riprese sovrapponibili per creare un mosaico (purtroppo non completo).

Sun Spots - 2014 07-06

Sono circa una decina di immagini da 400 frames ciascuna (su 1000 totali).
L’elaborazione è stata fatta sempre con registax, l’unione del mosaico con Hugin.

Continue reading...

Notice: this article is currently available in italian only.
I will translate it soon. You may contact me via comments if you want me to “prioritize” this article first.

template<typename T>
class Fill {
private:
  T *array;
  long _size;
  T _value;
public:
  Fill(T *a) : array(a) {}
  Fill &size(long s) { _size = s; return *this; }
  Fill &with(T value) { _value = value; return *this; }
  ~Fill() {
    for(long i=0; i<_size; i++) array[i] = _value;
  }
};

Utilizzo snippet:

int array[10];
Fill<int>(array).size(10).with(1);

Ecco un po’ di teoria di cosa succede.

RAII è una tecnica che permette di sfruttare una caratteristica del c++ che lo differenzia dai linguaggi con garbage collector (Java, ad esempio): la certezza di quando il distruttore della classe verrà chiamato.

L’idea è di sfruttare entrata ed uscita dallo scope di una variabile per effettuare acquisizione e deallocazione delle risorse. O per dirla in altri termini, per eseguire istruzioni all’ingresso e all’uscita di uno scope.

In questo caso stiamo creando una istanza anonima della classe Filler.

Alla sua inizializzazione passiamo al costruttore

Fill<int>(T *a) : array(a) {}

un array, che vogliamo riempire. Il costruttore lo memorizzerà nel suo field “array”.

Con il metodo “size” diciamo quanti elementi dell’array vogliamo riempire, mentre col metodo “with” impostiamo il valore con cui riempire l’array.

Entrambi questi metodi tornano un riferimento a “this”, ossia all’istanza corrente, in modo da “tenerla viva” nello scope, e permettendo di effettuare method chaining.

Infine, quando la variabile scompare dallo scope (ossia subito, visto che è anonima), viene chiamato il distruttore, che contiene il ciclo for che riempie l’array col valore che abbiamo impostato.

E’ interessante notare come, non essendoci nessun metodo che esplicitamente riempie l’array, l’ordine delle chiamate è perfettamente invertibile: avrei infatti potuto ugualmente scrivere

Fill<int>(array).with(1).size(10);

E funzionerebbe nello stesso identico modo, dato che il riempimento vero e proprio verrà comunque effettuato nel distruttore.

Si tratta ovviamente di un esempio relativamente banale, ma che fa intuire la potenza della tecnica.

Basti pensare ad altre applicazioni, come l’apertura di un file con chiusura automatica quando la variabile RAII esce dallo scope, o una transazione che inizia nel costruttore, e viene automaticamente committata nel distruttore, o addirittura, nel c++11, l’esecuzione di una lambda quando la variabile RAII esce dallo scope.

class Scope {
  public:
    Scope(std::function<void()> onExit) : _onExit(onExit) {}
    ~Scope() { _onExit(); }
  private:
    std::function<void()> _onExit;
};

RAII viene molto usato sopratutto per gestire al meglio le eccezioni: non è infatti necessario un blocco finally come in Java, dato che sia in caso di eccezione che nel flusso normale la variabile viene comunque deallocata, e il distruttore invocato.

Continue reading...

Notice: this article is currently available in italian only.
I will translate it soon. You may contact me via comments if you want me to “prioritize” this article first.

Dopo aver collimato un po’ meglio il telescopio, ho approfittato di una mattinata con un seeing tutto sommato accettabile per effettuare altre riprese del sole. Domenica 8 giugno il sole si mostrava particolarmente ricco, con un gruppo di macchie in particolare molto vicino, proprio al centro dell’astro, come mostrato dalla ripresa della sonda SOHO.

Sole ripreso dalla sonda SOHO
Sole ripreso dalla sonda SOHO

I gruppi da me ripresi sono il 2080-2085, molto estesi, e il 2082. Qui le riprese:

Sun Spots - 2014 06 08
Sun Spots - 2014 06 08

Continue reading...

Notice: this article is currently available in italian only.
I will translate it soon. You may contact me via comments if you want me to “prioritize” this article first.

Sempre per ingannare l’attesa del prossimo novilunio (e che almeno stavolta sia il meteo sia clemente), ho deciso di investire un po’ di vil denaro per acquistare una videocamera dedicata per la riprese planetarie, dato che il soggetto mi ha sempre attirato parecchio.
Si tratta di una QHY5L-II, versione monocromatica, sicuramente non il meglio, ma che mi ha molto colpito per il rapporto qualità/prezzo.

Oltre che per la simpatica scatolina di biscotti che viene fornita come custodia 🙂

QHY5l-IIm
QHY5l-IIm

Ho scelto una camera bianco e nero per poter avere una risoluzione maggiore, per effettuare riprese a colori sarà sufficiente acquistare dei filtri RGB una volta acquisita confidenza con la fotocamera. Inoltre ho preso la versione “L”, caratterizzata da una Q.E. del 74%. È anche piuttosto veloce, con un frame rate che raramente scende sotto i 30fps anche su soggetti un po’ meno luminosi come Saturno in queste sere, basso ed affogato dall’atmosfera terrestre.

Il software fornito per Windows è decisamente migliorabile, ma preso “con le buone” tutto sommato fa il suo dovere. Piuttosto lento nella scrittura dei fotogrammi su disco. Dovrei provare qualche software di terze parti come FireCapture.

Il supporto per GNU/Linux è parecchio traballante, le applicazioni che la supportano sono poche e funzionano maluccio, ma se non altro il produttore fornisce dei driver open source, e potrei pensare di creare io un’applicazione apposita di gestione della camera per ovviare ai problemi di cui sopra.

Intanto ho già fatto qualche prova, sia pure in condizioni di seeing parecchio svantaggiose. Il sensore si dimostra parecchio luminoso, permette un range di esposizioni particolarmente ampio (dai nanosecondi, fino ai 10 minuti) che lo rende piuttosto versatile. Penso che potrei addirittura provare a fare qualche ripresa su cielo profondo, in un prossimo futuro.

Visto appunto il seeing scarso non pubblico le prove su Saturno e sulla Luna, venute piuttosto maluccio (dovrei uscire ad osservare da qualche parte che non sia la finestra di casa per avere risultati accettabili). Pubblico invece qui in basso qualche prova effettuata sul sole con filtro Baader AstroSolar (neutro), sicuramente ancora molto migliorabili, ma che lasciano già vedere un buon livello di dettaglie sulle macchie, la granulazione, e le facolae.

Sunspots - 17/05/2014
Sunspots - 17/05/2014
Sunspots

Continue reading...

Notice: this article is currently available in italian only.
I will translate it soon. You may contact me via comments if you want me to “prioritize” this article first.

L’uscita dello scorso fine settimana, nonostante maltempo, nubi e anche un po’ di pioggia, è stata comunque piuttosto produttiva. Il panorama era davvero bello, il cielo  piuttosto scuro (finchè è durato), e ne abbiamo anche approfittato per fare qualche ripresa planetaria.

Panorama da Bogli. Foto di Alessia Rabaioli
Panorama da Bogli. Foto di Alessia Rabaioli

Saturno in particolare si prestava molto, ed abbiamo tentato di riprenderlo con il Dobson 200mm di Alessia (quindi senza inseguimento!) e la mia telecamera nuova.

Dato che sono pigro e che c’è chi scrive molto meglio di me lascio semplicemente due link al sito e al blog di Alessia con altre immagini ed elaborazioni.

Continue reading...

Notice: this article is currently available in italian only.
I will translate it soon. You may contact me via comments if you want me to “prioritize” this article first.

Mentre il maltempo imperversa impedendo di collaudare a dovere la nuova strumentazione, ne approfitto per fare qualche test “al buio” del nuovo setup, ad esempio per il pilotaggio software. Ho scelto la HEQ5 versione “Syntrek” per evitare la tentazione di abusare troppo del puntamento GOTO, e godere appieno del piacere “da smanettone” di riuscire a far tutto da se, compreso puntare quella galassietta particolarmente debole senza l’ausilio dell puntamento automatico… ma per tutte le evenienze ho comunque preso il cavetto di collegamento al pc, ed è comunque piacevole riuscire a costruire un perfetto sistema sostitutivo del più costoso telecomandino “SynScan” venduto normalmente con la montatura. Qui scriverò un semi-report di quanto son riuscito a combinare, del setup utilizzato, e suggerimenti utili per chi usa una configurazione simile alla mia.

Hardware

Per prima cosa, la montatura ovviamente: la mia è una SkyWatcher HEQ5 SynTrek (senza GOTO appunto). Quanto scritto sotto vale anche per altre varianti, come la HEQ5 con SynScan, la EQ5, o la EQ6, a patto di avere il collegamento al pc corrispondente. Per quanto riguarda il collegamento al pc: esistono due modi per collegare questo tipo di montature al pc. Uno è tramite il telecomando SynScan, che non ho preso appunto. Nel mio caso ho dovuto acquistare un interfacciamento chiamato “EQDIRECT“, che effettua il collegamento dalla porta della montatura (di tipo RJ45) a porta seriale o usb del computer. Ci sono diversi modi per acquistare questo tipo di cavo: da chi ha ideato originariamente l’interfacciamento, cioè ShoeString Astronomy, che ha diversi distributori nel mondo, Italia compres, a cloni più o meno simili, come quello che io ho acquistato presso Teleskop Express. Come computer va bene più o meno qualunque cosa, io in particolare utilizzo un netbook, che offre come vantaggi una grande trasportabilità, consumi molto ridotti e notevole durata della batteria.

Sistema Operativo e software non astronomico

Qui c’è decisamente l’imbarazzo della scelta, di distribuzioni GNU/Linux ce ne sono davvero tante, ognuno ha la sua preferita, e ci sono addirittura delle distribuzioni pronte per l’uso astronomico con tanto software dedicato già preinstallato. Io ho installato una variante di Ubuntu, LUbuntu, minimale, snella e veloce, particolarmente indicata per computer meno performanti come i netbook, appunto. Segnalo anche un software non direttamente legato all’astronomia, ma particolarmente utile: powertop, di Intel, che permette di ridurre notevolmente i consumi ed allungare la vita della batteria.

INDI e KStars

Naturalmente l’installazione di questi due software sarà ovviamente diversa per le varie distribuzioni GNU/Linux; per Ubuntu (e derivate, come LUbuntu), si può fare riferimento alla ben documentata pagina Downloads di INDI, che fornisce istruzioni anche per il repository ppa da aggiungere con pacchetti molto aggiornati e completi. In particolare, per la mia HEQ5, bisogna installare anche il pacchetto extra indi-eqmod non presente di default in ubuntu, ma presente nel ppa. Nel dubbio, si può installare il meta-pacchetto indi-full, che conterrà anche altri driver aggiuntivi (INDI può controllare non solo montature, ma anche macchine fotografiche, webcam, focheggiatori, etc etc). Installare quindi anche KStars (sudo apt-get install kstars).

Setup e utilizzo software

Configurare KStars per l’utilizzo della montatura può essere fuorviante, ma i passi da seguire sono comunque abbastanza semplici stando attenti ad alcune accortezze. Anzitutto, esiste un wizard di aggiunta telescopio, ma non è particolarmente più comodo rispetto al gestore dispositivi regolare, quindi useremo solo il secondo. Segue galleria di screenshots, nelle descrizioni di ognuno sono illustrati i passaggi da seguire.

Selezionare questa voce per lanciare il Device Manager INDI

Selezionare “EQMod” tra i telescopi disponibili

Nella Scheda “EQMod” selezionare il tab “Options”. Impostare la porta (dipende dal tipo di connessione usata), quindi per memorizzarla, premere il pulsante “Save”.

Pagina principale del dispositivo. Da qui possiamo vedere lo stato, le coordinate puntate, e le opzioni per il tracking. Come primissima cosa, per abilitare le operazioni, abilitare il tracking “Sideral”.

Nel tab “Motion Control” possiamo controllare manualmente la montatura per puntare e correggere. La combo “slew presets” ci permette anche di scegliere la velocità con cui effettuare i movimenti

Tornando a KStars e cliccando col tasto destro sul cielo (o ancor meglio su un oggetto) vediamo comparire la nuova voce di menù “EQMod” che ci permetterà di controllare la montatura.

Dall’ultimo screenshot sono particolarmente utili le seguenti azioni:

  • Center Crosshair: sposta l’inquadratura di KStars centrando la zona di cielo puntata dalla montatura.
  • Sync: particolarmente importante, permette di allineare la montatura. Non avendo encoders assoluti infatti, bisogna comunicare al software quale zona di cielo stiamo puntando per allineare la montatura. Possiamo quindi inquadrare manualmente una stella conosciuta col telescopio, selezionarla su KStars col tasto destro, e quindi cliccare Sync per effettuare l’allineamento.
  • Track e Slew, permettono invece di muovere la montatura verso l’oggetto selezionato.

Questo è quanto per un funzionamento “base” di KStars e INDI. In realtà il software è particolarmente ricco di opzioni e funzionalità, e merita sicuramente menzione Ekos, un tool interno a KStars particolarmente avanzato e molto indicato per astrofotografia, che offre molte opzioni utili per la ripresa delle immagini, la messa a fuoco (sia automatica che manuale), correzione automatica degli errori di puntamento della montatura, e tanto altro. Spero di testarlo a dovere, per approfondire l’argomento in un prossimo post.

Continue reading...