Index: trunk/FACT++/src/drivectrl.cc
===================================================================
--- trunk/FACT++/src/drivectrl.cc	(revision 13981)
+++ trunk/FACT++/src/drivectrl.cc	(revision 13982)
@@ -645,4 +645,18 @@
 // ------------------------------------------------------------------------
 
+struct Source
+{
+    Source() : ra(0), dec(0), offset(0)
+    {
+        angle[0] = angle[1] = 0;
+    }
+
+    double ra;
+    double dec;
+    double offset;
+    array<double, 2> angle;
+};
+
+
 template <class T, class S>
 class StateMachineDrive : public T, public ba::io_service, public ba::io_service::work
@@ -653,5 +667,5 @@
     string fDatabase;
 
-    typedef map<string,pair<double,double>> sources;
+    typedef map<string, Source> sources;
     sources fSources;
 
@@ -797,4 +811,61 @@
     }
 
+    const sources::const_iterator GetSourceFromDB(const char *ptr, const char *last)
+    {
+        if (find(ptr, last, '\0')==last)
+        {
+            T::Fatal("TrackWobble - The name transmitted by dim is not null-terminated.");
+            throw uint32_t(T::kSM_FatalError);
+        }
+
+        const string name(Tools::TrimQuotes(ptr));
+
+        const sources::const_iterator it = fSources.find(name);
+        if (it==fSources.end())
+        {
+            T::Error("Source '"+name+"' not found in list.");
+            throw uint32_t(T::GetCurrentState());
+        }
+
+        return it;
+    }
+
+    int TrackWobble(const EventImp &evt)
+    {
+        if (evt.GetSize()<=2)
+        {
+            ostringstream msg;
+            msg << "Track - Received event has " << evt.GetSize() << " bytes, but expected at least 3.";
+            T::Fatal(msg);
+            return T::kSM_FatalError;
+        }
+
+        const uint16_t wobble = evt.GetUShort();
+        if (wobble!=1 && wobble!=2)
+        {
+            ostringstream msg;
+            msg << "TrackWobble - Wobble id " << wobble << " undefined, only 1 and 2 allowed.";
+            T::Error(msg);
+            return T::GetCurrentState();
+        }
+
+        const char *ptr  = evt.Ptr<char>(2);
+        const char *last = ptr+evt.GetSize()-2;
+
+        try
+        {
+            const sources::const_iterator it = GetSourceFromDB(ptr, last);
+
+            const string &name = it->first;
+            const Source &src  = it->second;
+
+            return StartWobble(src.ra, src.dec, src.offset, src.angle[wobble-1], name);
+        }
+        catch (const uint32_t &e)
+        {
+            return e;
+        }
+    }
+
     int Track(const EventImp &evt)
     {
@@ -804,5 +875,5 @@
             msg << "Track - Received event has " << evt.GetSize() << " bytes, but expected at least 17.";
             T::Fatal(msg);
-            return false;
+            return T::kSM_FatalError;
         }
 
@@ -811,23 +882,17 @@
         const char   *last = ptr+evt.GetSize()-16;
 
-        if (find(ptr, last, '\0')==last)
-        {
-            T::Fatal("Track - The name transmitted by dim is not null-terminated.");
-            return false;
-        }
-
-        const string name(Tools::TrimQuotes(ptr));
-
-        const sources::const_iterator it = fSources.find(name);
-        if (it==fSources.end())
-        {
-            T::Error("Source '"+name+"' not found in list.");
-            return false;
-        }
-
-        const double &ra  = it->second.first;
-        const double &dec = it->second.second;
-
-        return StartWobble(ra, dec, dat[0], dat[1], name);
+        try
+        {
+            const sources::const_iterator it = GetSourceFromDB(ptr, last);
+
+            const string &name = it->first;
+            const Source &src  = it->second;
+
+            return StartWobble(src.ra, src.dec, dat[0], dat[1], name);
+        }
+        catch (const uint32_t &e)
+        {
+            return e;
+        }
     }
 
@@ -857,12 +922,12 @@
     int Print()
     {
-        for (sources::const_iterator it=fSources.begin();
-             it!=fSources.end(); it++)
+        for (auto it=fSources.begin(); it!=fSources.end(); it++)
         {
             const string &name = it->first;
-            const double &ra   = it->second.first;
-            const double &dec  = it->second.second;
-
-            T::Out() << name << "," << ra << "," << dec << endl;
+            const Source &src  = it->second;
+
+            T::Out() << name << ",";
+            T::Out() << src.ra       << "," << src.dec      << "," << src.offset << ",";
+            T::Out() << src.angle[0] << "," << src.angle[1] << endl;
         }
         return T::GetCurrentState();
@@ -1004,4 +1069,10 @@
              "|Offset[deg]:Wobble offset"
              "|Angle[deg]:Wobble angle"
+             "|Name[string]:Source name");
+
+        T::AddEvent("TRACK_WOBBLE", "S:1;C", State::kArmed, State::kTracking)   // ->RADEC/GRB
+            (bind(&StateMachineDrive::TrackWobble, this, placeholders::_1))
+            ("Move the telescope to the given wobble position around the given source and start tracking"
+             "|id:Wobble angle id (1 or 2)"
              "|Name[string]:Source name");
 
@@ -1133,15 +1204,16 @@
         for (vector<mysqlpp::Row>::const_iterator v=res.begin(); v<res.end(); v++)
         {
+            Source src;
+            src.ra  = (*v)[1];
+            src.dec = (*v)[2];
             const string name = (*v)[0].c_str();
-            const double ra   = (*v)[1];
-            const double dec  = (*v)[2];
 
             // FIXME: Check double names
-            fSources[name] = make_pair(ra, dec);
+            fSources[name] = src;
 
             if (print)
             {
                 ostringstream msg;
-                msg << " " << name << setprecision(8) << ":   Ra=" << ra << "h Dec=" << dec << "deg";
+                msg << " " << name << setprecision(8) << ":   Ra=" << src.ra << "h Dec=" << src.dec << "deg";
                 T::Message(msg);
             }
@@ -1183,6 +1255,10 @@
             if (i==3)
             {
+                Source src;
+                src.ra  = ra;
+                src.dec = dec;
+
                 // FIXME: Check double names
-                fSources[name] = make_pair(ra, dec);
+                fSources[name] = src;
             }
         }
