Page 1 of 1

No calibration result

PostPosted: 01 Aug 2015, 11:56
by jeroen.thunnissen
During a calibration I exchanged the following messages with the server: (all messages are preceded by a time stamp, sent messages by -->, received messages by <--)
Code: Select all
10:59:58.627   --> {"values":{"pointcount":9},"category":"calibration","request":"start"}
10:59:58.628   <-- {"category":"calibration","request":"start","statuscode":200}

10:59:59.663   --> {"values":{"x":108,"y":972},"category":"calibration","request":"pointstart"}
10:59:59.664   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:00.421   --> {"category":"calibration","request":"pointend"}
11:00:00.422   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:03.456   --> {"values":{"x":108,"y":540},"category":"calibration","request":"pointstart"}
11:00:03.457   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:04.213   --> {"category":"calibration","request":"pointend"}
11:00:04.213   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:07.256   --> {"values":{"x":108,"y":108},"category":"calibration","request":"pointstart"}
11:00:07.256   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:08.020   --> {"category":"calibration","request":"pointend"}
11:00:08.020   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:11.062   --> {"values":{"x":960,"y":108},"category":"calibration","request":"pointstart"}
11:00:11.062   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:11.825   --> {"category":"calibration","request":"pointend"}
11:00:11.826   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:14.884   --> {"values":{"x":1812,"y":108},"category":"calibration","request":"pointstart"}
11:00:14.885   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:15.652   --> {"category":"calibration","request":"pointend"}
11:00:15.652   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:18.674   --> {"values":{"x":960,"y":972},"category":"calibration","request":"pointstart"}
11:00:18.675   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:19.438   --> {"category":"calibration","request":"pointend"}
11:00:19.439   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:22.466   --> {"values":{"x":1812,"y":972},"category":"calibration","request":"pointstart"}
11:00:22.467   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:23.229   --> {"category":"calibration","request":"pointend"}
11:00:23.230   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:26.257   --> {"values":{"x":1812,"y":540},"category":"calibration","request":"pointstart"}
11:00:26.259   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:27.021   --> {"category":"calibration","request":"pointend"}
11:00:27.021   <-- {"category":"calibration","request":"pointend","statuscode":200}

11:00:30.071   --> {"values":{"x":960,"y":540},"category":"calibration","request":"pointstart"}
11:00:30.071   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:30.827   --> {"category":"calibration","request":"pointend"}
11:00:30.833   <-- {"category":"calibration","request":"pointend","statuscode":200,"values":{"calibresult":{"calibpoints":[
   {"acd":{"ad":0.0421,"adl":0.0421,"adr":0.0},"asdp":{"asd":105.1198,"asdl":89.2587,"asdr":0.0},"cp":{"x":108,"y":972},"mecp":{"x":107.0383,"y":971.0858},"mepix":{"mep":1.3269,"mepl":1.3269,"mepr":0.0},"state":2},
   {"acd":{"ad":0.0539,"adl":0.0539,"adr":0.0},"asdp":{"asd":131.4217,"asdl":102.5007,"asdr":0.0},"cp":{"x":108,"y":540},"mecp":{"x":106.9755,"y":538.6437},"mepix":{"mep":1.6997,"mepl":1.6997,"mepr":0.0},"state":2},
   {"acd":{"ad":0.0246,"adl":0.0246,"adr":0.0},"asdp":{"asd":139.7911,"asdl":107.6795,"asdr":0.0},"cp":{"x":108,"y":108},"mecp":{"x":107.2278,"y":108.0856},"mepix":{"mep":0.7770,"mepl":0.7770,"mepr":0.0},"state":2},
   {"acd":{"ad":0.0440,"adl":0.0440,"adr":0.0},"asdp":{"asd":75.0134,"asdl":65.9231,"asdr":0.0},"cp":{"x":960,"y":108},"mecp":{"x":959.8715,"y":109.3822},"mepix":{"mep":1.3882,"mepl":1.3882,"mepr":0.0},"state":2},
   {"acd":{"ad":0.0,"adl":0.0,"adr":0.0},"asdp":{"asd":0.0,"asdl":0.0,"asdr":0.0},"cp":{"x":1812,"y":108},"mecp":{"x":0.0,"y":0.0},"mepix":{"mep":0.0,"mepl":0.0,"mepr":0.0},"state":0},
   {"acd":{"ad":0.0,"adl":0.0,"adr":0.0},"asdp":{"asd":0.0,"asdl":0.0,"asdr":0.0},"cp":{"x":960,"y":972},"mecp":{"x":0.0,"y":0.0},"mepix":{"mep":0.0,"mepl":0.0,"mepr":0.0},"state":0},
   {"acd":{"ad":14.1201,"adl":14.1201,"adr":0.0},"asdp":{"asd":1414.1156,"asdl":1087.7661,"asdr":0.0},"cp":{"x":1812,"y":972},"mecp":{"x":1721.0668,"y":526.3952},"mepix":{"mep":454.7884,"mepl":454.7884,"mepr":0.0},"state":2},
   {"acd":{"ad":19.0660,"adl":19.0660,"adr":0.0},"asdp":{"asd":1017.6612,"asdl":929.3745,"asdr":0.0},"cp":{"x":1812,"y":540},"mecp":{"x":1674.0687,"y":1149.4298},"mepix":{"mep":624.8438,"mepl":624.8438,"mepr":0.0},"state":1},
   {"acd":{"ad":2.5638,"adl":2.5638,"adr":0.0},"asdp":{"asd":34.9237,"asdl":30.8928,"asdr":0.0},"cp":{"x":960,"y":540},"mecp":{"x":960.9404,"y":459.0540},"mepix":{"mep":80.9515,"mepl":80.9515,"mepr":0.0},"state":2}
],"deg":5.2631,"degl":5.2631,"degr":0.0,"num":9,"result":false}}}

11:00:33.932   --> {"values":{"x":1812,"y":108},"category":"calibration","request":"pointstart"}
11:00:33.933   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:34.695   --> {"category":"calibration","request":"pointend"}
11:00:34.695   <-- {"category":"calibration","request":"pointend","statuscode":200}
11:00:37.729   --> {"values":{"x":960,"y":972},"category":"calibration","request":"pointstart"}
11:00:37.730   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:38.486   --> {"category":"calibration","request":"pointend"}
11:00:38.487   <-- {"category":"calibration","request":"pointend","statuscode":200}
11:00:41.514   --> {"values":{"x":1812,"y":540},"category":"calibration","request":"pointstart"}
11:00:41.515   <-- {"category":"calibration","request":"pointstart","statuscode":200}
11:00:42.281   --> {"category":"calibration","request":"pointend"}
11:00:42.282   <-- {"category":"calibration","request":"pointend","statuscode":200}


No further messages from the server were received. Observe that the first calibration result, returned on the ninth pointend lists three points that should be resampled (states 0, 0 and 1). However upon resampling these three points no new calibration result is returned. My understanding of the API is that it should. Do I misunderstand or is this a bug?

Re: No calibration result

PostPosted: 03 Aug 2015, 11:10
by Martin
Hi Jeroen,

By the looks of it you are doing it right.

Consider this snippet from our C# Calibration UI.

Code: Select all
        public void OnCalibrationResult(CalibrationResult res)
        {
            // Invoke on UI thread
            if (this.Dispatcher.Thread != Thread.CurrentThread)
            {
                Dispatcher.BeginInvoke(new MethodInvoker(() => OnCalibrationResult(res)));
                return;
            }

            // No result?
            if (res == null || res.Calibpoints == null)
            {
                RaiseResult(CalibrationRunnerResult.Error, "Calibration result is empty.");
                StopAndClose();
                return;
            }

            Console.Out.WriteLine("CalibrationResult, avg: " + res.AverageErrorDegree + " left: " + res.AverageErrorDegreeLeft + " right: " + res.AverageErrorDegreeRight);

            // Success, check results for bad points
            foreach (CalibrationPoint cp in res.Calibpoints)
            {
                if (cp == null || cp.Coordinates == null)
                    continue;

                // Tracker tells us to resample this point, enque it
                if (cp.State == CalibrationPoint.STATE_RESAMPLE || cp.State == CalibrationPoint.STATE_NO_DATA)
                {
                    points.Enqueue(new Point2D(cp.Coordinates.X, cp.Coordinates.Y));
                    Console.Out.WriteLine("Recal adding " + cp.Coordinates.X + " " + cp.Coordinates.Y + " PointsInQueue: " + points.Count );
                }
            }

            // Time to stop?
            if (reSamplingCount > NUM_MAX_CALIBRATION_ATTEMPTS || points.Count > NUM_MAX_RESAMPLE_POINTS)
            {
                AbortCalibration(CalibrationRunnerResult.Failure, "Unable to calibrate.");
                StopAndClose();
                return;
            }

            // Resample?
            if (points != null && points.Count > 0)
            {
                reSamplingCount++;
                // Transition from last point to first resample point
                Point2D nextPos = points.Peek(); // peek here, RunPointSequence pulls out of queue
                DoubleAnimation cX = CreateTransitionAnimation(DPI * currentPoint.X, DPI * nextPos.X, transitionTimeMs);
                DoubleAnimation cY = CreateTransitionAnimation(DPI * currentPoint.Y, DPI * nextPos.Y, transitionTimeMs);
                cX.Completed += delegate { RunPointSequence(); }; // once moved, start sequence
                calPointWpf.BeginAnimation(Canvas.LeftProperty, cX);
                calPointWpf.BeginAnimation(Canvas.TopProperty, cY);
                return;
            }

            RaiseResult(CalibrationRunnerResult.Success, string.Empty, res);
            StopAndClose();
        }


Fairly straightforward logic. If we get notification from the server that there are points to be re-sampled we add them to the queue and run the procedure again. Once the server has received all points it will send the new results. We keep doing this until all points are good with limits: max three runs, no more than three bad points (better to do a fresh calibration).

Are you using any of the provided APIs or rolling your own socket? Server-version?

Re: No calibration result

PostPosted: 05 Aug 2015, 13:38
by jeroen.thunnissen
I am using the provided TETClient API (latest version) and am running server version 0.9.56 for Windows.

Re: No calibration result

PostPosted: 08 Aug 2015, 15:22
by jeroen.thunnissen
I have observed this behavior twice now. Can I report this as a bug somewhere?

Re: No calibration result

PostPosted: 10 Aug 2015, 10:41
by Martin
I will create a ticket in our bug tracking tool for this issue.

Are both of you using the latest version of the TET C# client from GitHub?

Re: No calibration result

PostPosted: 10 Aug 2015, 10:50
by jeroen.thunnissen
Yes.

Take note that I intercepted the above incoming server messages almost directly after being read from the socket in the Work method in TETCSharpClient.IncomingStreamHandler. It thus seems unlikely that the cause lies in TETCSharpClient, but rather in the server.

The following excerpt shows the logging code:
Code: Select all
private void Work()
        {
            try
            {
                reader = new StreamReader(socket.GetStream(), Encoding.ASCII);

                while (isRunning)
                {
                    try
                    {
                        while (!reader.EndOfStream)
                        {
                            string response = reader.ReadLine();

                            //MODIFICATION: added server logging
                            var myJsreader = new JsonTextReader(new StringReader(response));
                            var myJson = (JObject)new JsonSerializer().Deserialize(myJsreader);
                            JObject myValues = null != myJson[Protocol.KEY_VALUES] ? myJson[Protocol.KEY_VALUES].ToObject<JObject>() : null;
                            JToken frame = myValues != null ? myValues[Protocol.TRACKER_FRAME] : null;
                            if (frame == null && JsonConvert.DeserializeObject<ReplyBase>(response).Category != Protocol.CATEGORY_HEARTBEAT)
                            {
                                Logger.WriteString("<-- " + response, Logger.Category.Server);
                            }

                            if (null != responseListener && !string.IsNullOrEmpty(response))
                                responseListener.OnGazeApiResponse(response);
...

Re: No calibration result

PostPosted: 11 Aug 2015, 10:25
by Martin
Hi Jeroen,

Updated calibration results are intended to follow after the last resample point (e.g. when there's been 9 valid points sampled).

I'll double check v0.56 and get back to you.