38float* target_pos_xyz = NULL;
39float* target_var_xyz = NULL;
40int* target_IDs = NULL;
61 if(nrhs == 0 && nlhs == 0){
63 mexPrintf(
"Destroying tracker3d.\n");
65 free(target_pos_xyz); target_pos_xyz = NULL;
66 free(target_var_xyz); target_var_xyz = NULL;
67 free(target_IDs); target_IDs = NULL;
71 mexPrintf(
"tracker3d is already dead!\n");
75 else if(nrhs == 1 && nlhs == 0){
77 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"tracker3d is already initialised! First destroy it if you want to change its configuration.");
80 if(!mxIsStruct(prhs[0]))
81 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"Input must be a struct");
88 mxTmp = mxGetField(prhs[0],0,
"Np");
90 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'Np' is not defined");
91 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || (
int)mxGetScalar(mxTmp)<1 || (
int)mxGetScalar(mxTmp)>100)
92 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'Np' must be an integer between 1 and 100");
93 tpars.
Np = (int)mxGetScalar(mxTmp);
96 mxTmp = mxGetField(prhs[0],0,
"maxNactiveTargets");
98 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'maxNactiveTargets' is not defined");
99 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || (
int)mxGetScalar(mxTmp)<1 || (
int)mxGetScalar(mxTmp)>100)
100 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'maxNactiveTargets' must be an integer between 1 and 100");
104 mxTmp = mxGetField(prhs[0],0,
"noiseLikelihood");
106 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'noiseLikelihood' is not defined");
107 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 || mxGetScalar(mxTmp)>1)
108 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'noiseLikelihood' must be a scalar between 0 and 1");
112 mxTmp = mxGetField(prhs[0],0,
"measNoiseSD");
114 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'measNoiseSD' is not defined");
115 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0)
116 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'measNoiseSD' must be a scalar");
120 mxTmp = mxGetField(prhs[0],0,
"noiseSpecDen");
122 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'noiseSpecDen' is not defined");
123 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0)
124 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'noiseSpecDen' must be a scalar");
128 mxTmp = mxGetField(prhs[0],0,
"ALLOW_MULTI_DEATH");
130 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'ALLOW_MULTI_DEATH' is not defined");
131 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || (
int)mxGetScalar(mxTmp)<0 || (
int)mxGetScalar(mxTmp)>1)
132 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'ALLOW_MULTI_DEATH' must be 0 or 1");
136 mxTmp = mxGetField(prhs[0],0,
"init_birth");
138 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'init_birth' is not defined");
139 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 || mxGetScalar(mxTmp)>1)
140 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'init_birth' must be a scalar between 0 and 1");
144 mxTmp = mxGetField(prhs[0],0,
"alpha_death");
146 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'alpha_death' is not defined");
147 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 )
148 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'alpha_death' must be a scalar");
152 mxTmp = mxGetField(prhs[0],0,
"beta_death");
154 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'beta_death' is not defined");
155 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 )
156 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'beta_death' must be a scalar");
160 mxTmp = mxGetField(prhs[0],0,
"dt");
162 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'dt' is not defined");
163 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 )
164 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'dt' must be a scalar");
165 tpars.
dt = mxGetScalar(mxTmp);
168 mxTmp = mxGetField(prhs[0],0,
"W_avg_coeff");
170 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'W_avg_coeff' is not defined");
171 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 || mxGetScalar(mxTmp)>1)
172 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'W_avg_coeff' must be a scalar between 0 and 1");
176 mxTmp = mxGetField(prhs[0],0,
"FORCE_KILL_TARGETS");
178 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'FORCE_KILL_TARGETS' is not defined");
179 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || (
int)mxGetScalar(mxTmp)<0 || (
int)mxGetScalar(mxTmp)>1)
180 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'FORCE_KILL_TARGETS' must be 0 or 1");
184 mxTmp = mxGetField(prhs[0],0,
"forceKillDistance");
186 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'forceKillDistance' is not defined");
187 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 )
188 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'forceKillDistance' must be a scalar");
192 mxTmp = mxGetField(prhs[0],0,
"M0");
194 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'M0' is not defined");
195 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=6)
196 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'M0' must be a 6-element vector");
197 tmp = mxGetData(mxTmp);
198 for(
int jj = 0; jj<6; jj++)
199 tpars.
M0[jj] = (
float)tmp[jj];
202 mxTmp = mxGetField(prhs[0],0,
"P0");
204 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'P0' is not defined");
205 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=36)
206 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'P0' must be a 6-by-6 matrix (or a stacked 36-element vector)");
207 tmp = mxGetData(mxTmp);
208 for(
int jj = 0; jj<6; jj++)
209 for(
int kk=0; kk<6; kk++)
210 tpars.
P0[jj][kk] = (
float)tmp[jj*6+kk];
213 mxTmp = mxGetField(prhs[0],0,
"cd");
215 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'cd' is not defined");
216 if (mxIsComplex(mxTmp) || mxGetNumberOfElements(mxTmp)!=1 || mxGetScalar(mxTmp)<0 )
217 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"'cd' must be a scalar");
218 tpars.
cd = mxGetScalar(mxTmp);
221 mexPrintf(
"Creating tracker3d.\n");
226 else if(nrhs == 1 && nlhs == 2){
228 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"safmex_tracker3d is uninitialised!");
232 const mwSize *pDims_mx;
233 nDims_mx = mxGetNumberOfDimensions(prhs[0]);
234 pDims_mx = mxGetDimensions(prhs[0]);
236 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"Observations must be N x 3 (x,y,z)");
238 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"Observations must be N x 3 (x,y,z)");
241 float* newObs_xyz = NULL;
247 tracker3d_step(hT3d, newObs_xyz, nObs, &target_pos_xyz, &target_var_xyz, &target_IDs, &nTargets);
251 plhs[0] = mxCreateDoubleMatrix( 0, 0, mxREAL );
252 plhs[1] = mxCreateDoubleMatrix( 0, 0, mxREAL );
256 pDims =
realloc1d(pDims, nDims*
sizeof(
int));
272 mexErrMsgIdAndTxt(
"MyToolbox:inputError",
"Unrecognised input/output configuration, refer to help instructions.");
void tracker3d_destroy(void **const phT3d)
Destroys an instance of the mighty tracker3d.
void tracker3d_step(void *const hT3d, float *newObs_xyz, int nObs, float **target_pos_xyz, float **target_var_xyz, int **target_IDs, int *nTargets)
Tracker time step to update & predict current target locations and to parse new measurements/observat...
void tracker3d_create(void **const phT3d, tracker3d_config tpars)
Creates an instance of the mighty tracker3d.
void * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
Main include header for safmex.
void MEXdouble2SAFsingle(const mxArray *in, float **out, int *nDims, int **pDims)
Convert a mex double-precision array into single precision array for SAF.
void SAFsingle2MEXdouble_int(int *in, int nDims, int *dims, mxArray **out)
Convert a single precision array used by SAF to mex double-precision array (integers)
void SAFsingle2MEXdouble(float *in, int nDims, int *dims, mxArray **out)
Convert a single precision array used by SAF to mex double-precision array.
User parameters for tracker3d.
float dt
Elapsed time (in seconds) between observations/measurements.
float M0[6]
[0,1,2] Position of sound source PRIORs (x,y,z), [3,4,5] Mean velocity PRIORs (x,y,...
float cd
PRIOR probability of noise.
float init_birth
PRIOR probability of birth [0 1].
float measNoiseSD
Measurement noise standard deviation.
int ALLOW_MULTI_DEATH
FLAG whether to allow for multiple target deaths in the same tracker prediction step.
int FORCE_KILL_TARGETS
FLAG force kill targets that are too close to one another.
float P0[6][6]
Diagonal matrix, [0,1,2] Variance PRIORs of estimates along the x,y,z axes; [3,4,5] Velocity PRIORs o...
int maxNactiveTargets
Maximum number of simultaneous targets permitted.
float forceKillDistance
Euclidian distance at which to kill targets that come too close to other (older) targets (<=).
float beta_death
Coefficient influencing the likelihood that a target will die; always >= 1.
float alpha_death
Coefficient influencing the likelihood that a target will die; always >= 1.
int Np
Number of Monte Carlo samples/particles.
float noiseLikelihood
Likelihood of an estimate being noise/clutter between [0..1].
float W_avg_coeff
Real-time tracking is based on the particle with highest weight.
float noiseSpecDen
Noise spectral density; influences the smoothness of the traget tracks.