diff --git a/README.md b/README.md
index e63ad30..fc13821 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,4 @@
-
-
-
+![FicTrac: The webcam-based method for tracking spherical motion and generating fictive animal paths](https://user-images.githubusercontent.com/3844483/110451048-176e9300-80c4-11eb-8e1e-e96545d7d2ed.jpg)
**FicTrac** is an open-source software library for reconstructing the fictive path of an animal walking on a patterned sphere. The software is fast, flexible, easy to use, and simplifies the setup of closed-loop tracking experiments.
@@ -53,7 +51,7 @@ The FicTrac source code can be built for both Windows and Linux (e.g. Ubuntu) op
2. Linux only:
1. Run the following from terminal to install necessary build tools and dependencies:
```
- [Linux] sudo apt-get install gcc g++ git cmake curl unzip tar yasm pkg-config libgtk2.0-dev libavformat-dev libavcodec-dev libavresample-dev libswscale-dev libopencv-dev
+ sudo apt-get install gcc g++ git cmake curl unzip tar yasm pkg-config libgtk2.0-dev libavformat-dev libavcodec-dev libavresample-dev libswscale-dev libopencv-dev
```
3. (Windows and Linux) Clone or download the [Vcpkg](https://github.com/Microsoft/vcpkg) repository and then follow the guide to install (make sure to perform the bootstrap and integration steps).
4. Using Vcpkg, install remaining dependencies:
@@ -125,7 +123,7 @@ Before running FicTrac, you may configure your camera (frame rate, resolution, e
Basler Pylon SDK
1. Download and install the latest [Pylon SDK](https://www.baslerweb.com/en/products/software/basler-pylon-camera-software-suite/).
-2. When preparing the build files for FicTrac using Cmake, you will need to specify to use Pylon using the switch `-D PGR_USB3=ON` and depending on where you installed the SDK, you may also need to provide the SDK directory path using the switch `-D BASLER_DIR=...`. For example, for a Windows installation you would replace step 3 above with (replacing with the path to your vcpkg root directory):
+2. When preparing the build files for FicTrac using Cmake, you will need to specify to use Pylon using the switch `-D BASLER_USB3=ON` and depending on where you installed the SDK, you may also need to provide the SDK directory path using the switch `-D BASLER_DIR=...`. For example, for a Windows installation you would replace step 3 above with (replacing with the path to your vcpkg root directory):
```
cmake -A x64 -D CMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake -D BASLER_USB3=ON -D BASLER_DIR="C:\path\to\Pylon" ..
```
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index f6e44f0..2e67e7a 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -5,8 +5,8 @@
# https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=azure-devops&tabs=yaml
trigger:
-#- master
-- develop
+- master
+#- develop
# We can run multiple jobs in parallel.
# see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases
diff --git a/doc/params.md b/doc/params.md
index 6173d25..9876b6c 100644
--- a/doc/params.md
+++ b/doc/params.md
@@ -24,7 +24,7 @@ In the table below, the various possible parameters are listed. If nothing is li
| thr_ratio | float | 1.25 | (0,inf) | Only if you need to | Adjusts the adaptive thresholding of the input image. Values > 1 will favour foreground regions (more white in thresholded image) and values < 1 will favour background regions (more black in thresholded image). |
| thr_win_pc | float | 0.2 | \[0,1] | Only if you need to | Adjusts the size of the neighbourhood window to use for adaptive thresholding of the input image, specified as a percentage of the width of the tracking window. Larger values avoid over-segmentation, whilst smaller values make segmentation more robust to illumination gradients on the trackball. |
| vid_codec | string | h264 | [h264,xvid,mpg4,mjpg,raw] | Only if you need to | Specifies the video codec to use when writing output videos (see `save_raw` and `save_debug`). |
-| sphere_map_fn | string | | | Only if you need to | If specified, FicTrac will attempt to load a previously generated sphere surface map from this filename. |
+| sphere_map_fn | string | | | Only if you need to | If specified, FicTrac will attempt to load a previously generated sphere surface map from this filename. Note that if you set this option, you should probably also set `opt_do_global` otherwise FicTrac may not find the initial sphere attitude. |
| | | | | | |
| opt_max_evals | int | 50 | (0,inf) | Probably not | Specifies the maximum number of minimisation iterations to perform each frame. Smaller values may improve tracking frame rate at the risk of finding sub-optimal matches. Number of optimisation iterations is printed to screen during tracking (its=...). |
| opt_bound | float | 0.35 | (0,inf) | Probably not | Specifies the optimisation search range in radians. Larger values will facilitate more track ball rotation per frame, but result in slower tracking and also possibly lead to false matches. |
diff --git a/include/typesvars.h b/include/typesvars.h
index 9119f1c..9a01dee 100644
--- a/include/typesvars.h
+++ b/include/typesvars.h
@@ -15,8 +15,3 @@ const CmReal CM_PI = 3.14159265358979323846;
const CmReal CM_PI_2 = 1.57079632679489661923;
const CmReal CM_R2D = 180.0 / CM_PI;
const CmReal CM_D2R = CM_PI / 180.0;
-
-//enum THR_MODE {
-// ADAPT,
-// NORM_PRIORS
-//};
diff --git a/scripts/socket_client.py b/scripts/socket_client.py
index 8a62b51..e7e8799 100644
--- a/scripts/socket_client.py
+++ b/scripts/socket_client.py
@@ -1,58 +1,75 @@
#!/usr/bin/env python3
import socket
+import select
HOST = '127.0.0.1' # The (receiving) host IP address (sock_host)
PORT = ???? # The (receiving) host port (sock_port)
+# TCP
# Open the connection (ctrl-c / ctrl-break to quit)
-with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: # UDP
-#with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: # TCP
- sock.bind((HOST, PORT)) # UDP
-# sock.connect((HOST, PORT)) # TCP
-
- data = ""
+#with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+# sock.connect((HOST, PORT))
+
+# UDP
+# Open the connection (ctrl-c / ctrl-break to quit)
+with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
+ sock.bind((HOST, PORT))
+ sock.setblocking(0)
# Keep receiving data until FicTrac closes
+ data = ""
+ timeout_in_seconds = 1
while True:
- # Receive one data frame
- new_data = sock.recv(1024)
- if not new_data:
- break
-
- # Decode received data
- data += new_data.decode('UTF-8')
-
- # Find the first frame of data
- endline = data.find("\n")
- line = data[:endline] # copy first frame
- data = data[endline+1:] # delete first frame
-
- # Tokenise
- toks = line.split(", ")
-
- # Check that we have sensible tokens
- if ((len(toks) < 24) | (toks[0] != "FT")):
- print('Bad read')
- continue
-
- # Extract FicTrac variables
- # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
- cnt = int(toks[1])
- dr_cam = [float(toks[2]), float(toks[3]), float(toks[4])]
- err = float(toks[5])
- dr_lab = [float(toks[6]), float(toks[7]), float(toks[8])]
- r_cam = [float(toks[9]), float(toks[10]), float(toks[11])]
- r_lab = [float(toks[12]), float(toks[13]), float(toks[14])]
- posx = float(toks[15])
- posy = float(toks[16])
- heading = float(toks[17])
- step_dir = float(toks[18])
- step_mag = float(toks[19])
- intx = float(toks[20])
- inty = float(toks[21])
- ts = float(toks[22])
- seq = int(toks[23])
+ # Check to see whether there is data waiting
+ ready = select.select([sock], [], [], timeout_in_seconds)
+
+ # Only try to receive data if there is data waiting
+ if ready[0]:
+ # Receive one data frame
+ new_data = sock.recv(1024)
+
+ # Uh oh?
+ if not new_data:
+ break
+
+ # Decode received data
+ data += new_data.decode('UTF-8')
+
+ # Find the first frame of data
+ endline = data.find("\n")
+ line = data[:endline] # copy first frame
+ data = data[endline+1:] # delete first frame
+
+ # Tokenise
+ toks = line.split(", ")
+
+ # Check that we have sensible tokens
+ if ((len(toks) < 24) | (toks[0] != "FT")):
+ print('Bad read')
+ continue
+
+ # Extract FicTrac variables
+ # (see https://github.com/rjdmoore/fictrac/blob/master/doc/data_header.txt for descriptions)
+ cnt = int(toks[1])
+ dr_cam = [float(toks[2]), float(toks[3]), float(toks[4])]
+ err = float(toks[5])
+ dr_lab = [float(toks[6]), float(toks[7]), float(toks[8])]
+ r_cam = [float(toks[9]), float(toks[10]), float(toks[11])]
+ r_lab = [float(toks[12]), float(toks[13]), float(toks[14])]
+ posx = float(toks[15])
+ posy = float(toks[16])
+ heading = float(toks[17])
+ step_dir = float(toks[18])
+ step_mag = float(toks[19])
+ intx = float(toks[20])
+ inty = float(toks[21])
+ ts = float(toks[22])
+ seq = int(toks[23])
+
+ # Do something ...
+ print(cnt)
- # Do something ...
- print(cnt)
+ else:
+ # Didn't find any data - try again
+ print('retrying...')
diff --git a/src/Trackball.cpp b/src/Trackball.cpp
index 33a0fa9..6b11d4e 100644
--- a/src/Trackball.cpp
+++ b/src/Trackball.cpp
@@ -864,12 +864,15 @@ void Trackball::updateSphere()
uint8_t& map = _sphere_map.data[py * _sphere_map.step + px];
// update map tile
- if (map == 128) {
+ if ((map == 0) || (map == 255)) {
+ // map tile frozen
+ good++;
+ } else if (map == 128) {
// map tile previously unseen
map = (proi[j] == 255) ? (128 + SPHERE_MAP_FIRST_HIT_BONUS) : (128 - SPHERE_MAP_FIRST_HIT_BONUS);
} else {
good++;
- map = min(max((proi[j] == 255) ? (int(map) + 1) : (int(map) - 1), 0), 255);
+ map = (proi[j] == 255) ? (map + 1) : (map - 1);
}
// display
diff --git a/test/3axis0.avi b/test/3axis0.avi
deleted file mode 100644
index 6345e6c..0000000
Binary files a/test/3axis0.avi and /dev/null differ
diff --git a/test/3axis0.cfg b/test/3axis0.cfg
deleted file mode 100644
index dc2953b..0000000
--- a/test/3axis0.cfg
+++ /dev/null
@@ -1,22 +0,0 @@
-## FicTrac config file (build Mar 10 2020)
-c2a_cnrs_xy : { 0, 0, 640, 0, 640, 640, 0, 640 }
-c2a_r : { -0.000000, 0.000000, 1.570796 }
-c2a_src : c2a_cnrs_xy
-c2a_t : { -0.000000, -0.000000, 0.288675 }
-do_display : y
-max_bad_frames : -1
-opt_bound : 0.350000
-opt_do_global : n
-opt_max_err : -1.000000
-opt_max_evals : 50
-opt_tol : 0.001000
-q_factor : 6
-roi_circ : { 250, 318, 268, 274, 301, 253, 357, 262, 387, 304, 378, 355, 309, 387 }
-roi_ignr : { }
-save_debug : n
-save_raw : n
-src_fn : 3axis0.avi
-src_fps : -1.000000
-thr_ratio : 1.250000
-thr_win_pc : 0.250000
-vfov : 120
diff --git a/test/3axis0_gt.csv b/test/3axis0_gt.csv
deleted file mode 100644
index 98cda58..0000000
--- a/test/3axis0_gt.csv
+++ /dev/null
@@ -1,100 +0,0 @@
-0,-0,0
--0.051106,0.19408,-0.12047
--0.076408,0.39394,-0.22629
--0.074381,0.59669,-0.31494
--0.043754,0.79869,-0.38395
-0.016309,0.99551,-0.43098
-0.10599,1.1819,-0.45397
-0.22456,1.352,-0.45129
-0.37012,1.4992,-0.42193
-0.53939,1.6165,-0.36574
-0.7275,1.6974,-0.28363
-0.92799,1.7356,-0.17777
-1.133,1.7264,-0.051613
-1.3335,1.6669,0.090127
-1.5202,1.5566,0.24176
-1.6839,1.3977,0.39702
-1.8163,1.1948,0.54954
-1.911,0.9548,0.69344
-1.9633,0.68624,0.82374
-1.9708,0.39836,0.93671
-1.9331,0.10051,1.03
-1.8516,-0.1985,1.1028
-1.7288,-0.49077,1.1552
-1.5683,-0.76959,1.1888
-1.3742,-1.0294,1.2058
-1.1508,-1.2659,1.2089
-0.90248,-1.4757,1.2014
-0.63344,-1.6562,1.187
-0.3479,-1.8054,1.1695
-0.049999,-1.922,1.1529
--0.25613,-2.0047,1.1412
--0.56619,-2.0527,1.1388
--0.87553,-2.0653,1.1499
--1.179,-2.042,1.179
--1.4705,-1.9826,1.2301
--1.7433,-1.8872,1.3072
--1.989,-1.7569,1.4136
--2.1983,-1.5934,1.5513
-2.2179,1.3156,-1.6166
-2.171,1.0421,-1.6904
-2.084,0.79183,-1.7846
-1.9622,0.56789,-1.8965
-1.8101,0.37261,-2.0233
-1.6314,0.20788,-2.1624
-1.4295,0.075339,-2.3108
-1.2068,-0.023423,-2.4655
-0.96562,-0.086745,-2.6234
-0.70777,-0.11277,-2.7807
-0.43478,-0.099389,-2.9332
-0.14807,-0.044155,-3.0758
-0.14483,-0.053407,3.0728
-0.40491,-0.17846,2.9063
-0.62427,-0.32131,2.7073
-0.80366,-0.47505,2.4824
-0.94557,-0.63394,2.2374
-1.0535,-0.79341,1.9769
-1.1316,-0.94994,1.7048
-1.1841,-1.1009,1.424
-1.2152,-1.2443,1.137
-1.2291,-1.3788,0.84584
-1.2298,-1.5036,0.55219
-1.2212,-1.6183,0.25754
-1.2073,-1.7225,-0.036713
-1.192,-1.8166,-0.32917
-1.1793,-1.9007,-0.61829
-1.1734,-1.9756,-0.90229
-1.179,-2.042,-1.179
-1.201,-2.1009,-1.4454
-1.2451,-2.1536,-1.6979
--1.2604,2.106,1.8474
--1.1987,1.889,1.7981
--1.1648,1.692,1.7067
--1.1555,1.5171,1.5814
--1.1678,1.3655,1.4291
--1.1989,1.2375,1.2554
--1.2457,1.1332,1.0648
--1.3059,1.0524,0.86078
--1.3769,0.99481,0.64645
--1.4565,0.9601,0.42426
--1.5427,0.94795,0.1963
--1.6335,0.95804,-0.035632
--1.7271,0.9901,-0.26996
--1.8216,1.0439,-0.50529
--1.9154,1.1193,-0.7403
--2.0067,1.216,-0.97379
--2.0937,1.334,-1.2046
--2.1747,1.4732,-1.4315
-2.1204,-1.5407,1.5596
-1.859,-1.4593,1.5032
-1.6105,-1.3742,1.4155
-1.3758,-1.2829,1.3043
-1.1555,-1.1835,1.1757
-0.95014,-1.0747,1.0347
-0.76026,-0.95536,0.88559
-0.58662,-0.82468,0.73195
-0.43011,-0.6823,0.577
-0.29183,-0.52814,0.42365
-0.17308,-0.3625,0.27462
-0.075274,-0.18608,0.13255
--3.9288e-15,-1.019e-13,-7.8575e-15
diff --git a/test/test.py b/test/test.py
deleted file mode 100644
index f0010da..0000000
--- a/test/test.py
+++ /dev/null
@@ -1,64 +0,0 @@
-import sys
-import csv
-import numpy as np
-import matplotlib.pyplot as plt
-import glob
-import subprocess
-import os
-
-if (len(sys.argv) < 2):
- print('Needs at least test name!')
- sys.exit()
-
-test_name = sys.argv[1]
-
-print('Processing test {}'.format(test_name))
-
-cfg_fn = test_name+'.cfg'
-
-print('Using cfg: {}'.format(cfg_fn))
-
-gt_csv = test_name+'_gt.csv'
-
-print('Using gt: {}'.format(gt_csv))
-
-if os.name == 'nt':
- cmd = "..\\bin\\Release\\fictrac.exe"
-else:
- cmd = "..\\bin\\Release\\fictrac"
-
-subprocess.run([cmd, cfg_fn])
-
-dat_list = glob.glob(test_name+'-*.dat')
-
-print('Found {} dat files matching pattern {}'.format(len(dat_list), test_name))
-
-dat_fn = dat_list[-1]
-
-print('Using dat: {}'.format(dat_fn))
-
-with open(gt_csv, 'r') as f:
- tmp = list(csv.reader(f))
- gt = np.array([[float(i) for i in x] for x in tmp])
-
-with open(dat_fn, 'r') as f:
- tmp = list(csv.reader(f))
- dat = np.array([[float(i) for i in x] for x in tmp])
- dat = dat[:,8:11]
-
-err = np.linalg.norm(gt - dat, axis=1)
-max_err = np.max(err)
-end_err = err[-1]
-
-print('max_err: {} end_err: {}'.format(max_err, end_err))
-
-plt.figure(1)
-plt.plot(gt)
-plt.plot(dat)
-plt.grid()
-
-plt.figure(2)
-plt.plot(err)
-plt.grid()
-
-plt.show()
diff --git a/test/test_3axis0.m b/test/test_3axis0.m
deleted file mode 100644
index a35f5bb..0000000
--- a/test/test_3axis0.m
+++ /dev/null
@@ -1,46 +0,0 @@
-function [max_err, end_err] = test_3axis0(dat_fn)
-
-dat = load(dat_fn);
-test = dat(:,9:11)
-
-rotx = @(t) [1 0 0; 0 cos(t) -sin(t) ; 0 sin(t) cos(t)] ;
-roty = @(t) [cos(t) 0 sin(t) ; 0 1 0 ; -sin(t) 0 cos(t)] ;
-rotz = @(t) [cos(t) -sin(t) 0 ; sin(t) cos(t) 0 ; 0 0 1] ;
-
-% rotate <360,1080,720>*clock
-R = deg2rad([360,1080,720]);
-t = linspace(0,100,100);
-
-rlist = zeros(100,3);
-for i = 1:100
- dR = t(i) .* R;
-
- A = eye(3);
- A = rotx(dR(1)) * A;
- A = roty(dR(2)) * A;
- A = rotz(dR(3)) * A;
-
- r = rotationMatrixToVector(A);
- rlist(i,:) = r;
-end
-
-% hmm..
-rlist(:,2) = -rlist(:,2);
-
-err = vecnorm(rlist - test, 2, 2);
-max_err = max(err);
-end_err = err(end);
-
-figure(1);
-hold off;
-plot(rlist);
-hold on;
-plot(test, 'x-');
-grid on;
-
-figure(2);
-hold off;
-plot(err);
-grid on;
-
-csvwrite('3axis0_gt.csv', rlist);