From 481d85dab37febf6c60b9897f77ee1895dc964b5 Mon Sep 17 00:00:00 2001 From: "Simon D. Levy" Date: Tue, 16 Sep 2014 20:34:06 -0400 Subject: [PATCH] Renamed mex_coreslam.* to mex_breezyslam --- matlab/Map.m | 8 +- matlab/RMHC_SLAM.m | 4 +- matlab/Scan.m | 6 +- matlab/make.m | 2 +- matlab/mex_breezyslam.c | 300 ++++++++++++++++++++++++++++++++ matlab/mex_breezyslam.mexa64 | Bin 0 -> 23528 bytes matlab/mex_breezyslam.mexmaci64 | Bin 0 -> 23440 bytes matlab/mex_breezyslam.mexw64 | Bin 0 -> 18432 bytes 8 files changed, 310 insertions(+), 10 deletions(-) create mode 100644 matlab/mex_breezyslam.c create mode 100755 matlab/mex_breezyslam.mexa64 create mode 100644 matlab/mex_breezyslam.mexmaci64 create mode 100644 matlab/mex_breezyslam.mexw64 diff --git a/matlab/Map.m b/matlab/Map.m index b36713b..e3f960e 100644 --- a/matlab/Map.m +++ b/matlab/Map.m @@ -26,13 +26,13 @@ classdef Map function map = Map(size_pixels, size_meters) % Map creates an empty square map % map = Map(size_pixels, size_meters) - map.c_map = mex_coreslam('Map_init', size_pixels, size_meters); + map.c_map = mex_breezyslam('Map_init', size_pixels, size_meters); end function disp(map) % Displays data about this map - mex_coreslam('Map_disp', map.c_map) + mex_breezyslam('Map_disp', map.c_map) end @@ -40,7 +40,7 @@ classdef Map % Updates this map with a new scan and position % % update(map, scan, new_position, map_quality, hole_width_mm) - mex_coreslam('Map_update', map.c_map, scan.c_scan, new_position, int32(map_quality), hole_width_mm) + mex_breezyslam('Map_update', map.c_map, scan.c_scan, new_position, int32(map_quality), hole_width_mm) end @@ -50,7 +50,7 @@ classdef Map % bytes = get(map) % Transpose for uniformity with Python, C++ versions - bytes = mex_coreslam('Map_get', map.c_map)'; + bytes = mex_breezyslam('Map_get', map.c_map)'; end diff --git a/matlab/RMHC_SLAM.m b/matlab/RMHC_SLAM.m index d146de9..0062574 100644 --- a/matlab/RMHC_SLAM.m +++ b/matlab/RMHC_SLAM.m @@ -45,7 +45,7 @@ classdef RMHC_SLAM < SinglePositionSLAM random_seed = floor(cputime) & hex2dec('FFFF'); end - slam.c_randomizer = mex_coreslam('Randomizer_init', random_seed); + slam.c_randomizer = mex_breezyslam('Randomizer_init', random_seed); end @@ -55,7 +55,7 @@ classdef RMHC_SLAM < SinglePositionSLAM % better position based on a starting position. [new_pos.x_mm,new_pos.y_mm,new_pos.theta_degrees] = ... - mex_coreslam('rmhcPositionSearch', ... + mex_breezyslam('rmhcPositionSearch', ... start_pos, ... slam.map.c_map, ... slam.scan_for_distance.c_scan, ... diff --git a/matlab/Scan.m b/matlab/Scan.m index 17fad78..4845738 100644 --- a/matlab/Scan.m +++ b/matlab/Scan.m @@ -41,14 +41,14 @@ classdef Scan span = 1; end - [scan.c_scan, scan.c_laser] = mex_coreslam('Scan_init', laser, span); + [scan.c_scan, scan.c_laser] = mex_breezyslam('Scan_init', laser, span); end function disp(scan) % Displays information about this Scan - mex_coreslam('Scan_disp', scan.c_scan) + mex_breezyslam('Scan_disp', scan.c_scan) end @@ -59,7 +59,7 @@ classdef Scan % hole_width_mm is the width of holes (obstacles, walls) in millimeters. % velocities is an optional list[dxy_mm, dtheta_degrees] % i.e., robot's (forward, rotational velocity) for improving the quality of the scan. - mex_coreslam('Scan_update', scan.c_scan, scan.c_laser, int32(scans_mm), hole_width_mm, velocities) + mex_breezyslam('Scan_update', scan.c_scan, scan.c_laser, int32(scans_mm), hole_width_mm, velocities) end end diff --git a/matlab/make.m b/matlab/make.m index 67798f4..b00df47 100644 --- a/matlab/make.m +++ b/matlab/make.m @@ -16,4 +16,4 @@ % along with this code. If not, see . -mex mex_coreslam.c ../c/coreslam.c ../c/coreslam_sisd.c ../c/random.c ../c/ziggurat.c +mex mex_breezyslam.c ../c/coreslam.c ../c/coreslam_sisd.c ../c/random.c ../c/ziggurat.c diff --git a/matlab/mex_breezyslam.c b/matlab/mex_breezyslam.c new file mode 100644 index 0000000..ad2d193 --- /dev/null +++ b/matlab/mex_breezyslam.c @@ -0,0 +1,300 @@ +/* + * mex_breezyslam.c : C extensions for BreezySLAM in Matlab + * + * Copyright (C) 2014 Simon D. Levy + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +#include "mex.h" + +#include "../c/coreslam.h" +#include "../c/random.h" + +#define MAXSTR 100 + +/* Helpers ------------------------------------------------------------- */ + +static int _streq(char * s, const char * t) +{ + return !strcmp(s, t); +} + +static void _insert_obj_lhs(mxArray *plhs[], void * obj, int pos) +{ + long * outptr = NULL; + + plhs[pos] = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + + outptr = (long *) mxGetPr(plhs[pos]); + + mexMakeMemoryPersistent(obj); + + *outptr = (long)obj; +} + +static double _get_field(const mxArray * pm, const char * fieldname) +{ + mxArray * field_array_ptr = mxGetField(pm, 0, fieldname); + + return mxGetScalar(field_array_ptr); +} + +static long _rhs2ptr(const mxArray * prhs[], int index) +{ + long * inptr = (long *) mxGetPr(prhs[index]); + + return *inptr; +} + +static scan_t * _rhs2scan(const mxArray * prhs[], int index) +{ + long inptr = _rhs2ptr(prhs, index); + + return (scan_t *)inptr; +} + +static map_t * _rhs2map(const mxArray * prhs[], int index) +{ + long inptr = _rhs2ptr(prhs, index); + + return (map_t *)inptr; +} + +static position_t _rhs2pos(const mxArray * prhs[], int index) +{ + position_t position; + + position.x_mm = _get_field(prhs[index], "x_mm"); + position.y_mm = _get_field(prhs[index], "y_mm"); + position.theta_degrees = _get_field(prhs[index], "theta_degrees"); + + return position; +} + +static void _rhs2laser(laser_t * laser, const mxArray * prhs[], int index) +{ + laser->scan_size = (int)_get_field(prhs[index], "scan_size"); + laser->scan_rate_hz = _get_field(prhs[index], "scan_rate_hz"); + laser->detection_angle_degrees = _get_field(prhs[index], "detection_angle_degrees"); + laser->distance_no_detection_mm = _get_field(prhs[index], "distance_no_detection_mm"); + laser->detection_margin = (int)_get_field(prhs[index], "detection_margin"); + laser->offset_mm = _get_field(prhs[index], "offset_mm"); +} + +/* Class methods ------------------------------------------------------- */ + +static void _map_init(mxArray *plhs[], const mxArray * prhs[]) +{ + + int size_pixels = (int)mxGetScalar(prhs[1]); + + double size_meters = mxGetScalar(prhs[2]); + + map_t * map = (map_t *)mxMalloc(sizeof(map_t)); + + map_init(map, size_pixels, size_meters); + + _insert_obj_lhs(plhs, map, 0); +} + +static void _map_disp(const mxArray * prhs[]) +{ + char str[MAXSTR]; + + map_t * map = _rhs2map(prhs, 1); + + map_string(*map, str); + + printf("%s\n", str); +} + +static void _map_update(const mxArray * prhs[]) +{ + map_t * map = _rhs2map(prhs, 1); + + scan_t * scan = _rhs2scan(prhs, 2); + + position_t position = _rhs2pos(prhs, 3); + + int map_quality = (int)mxGetScalar(prhs[4]); + + double hole_width_mm = mxGetScalar(prhs[5]); + + map_update(map, scan, position, map_quality, hole_width_mm); +} + +static void _map_get(mxArray *plhs[], const mxArray * prhs[]) +{ + map_t * map = _rhs2map(prhs, 1); + + unsigned char * pointer = NULL; + + plhs[0] = mxCreateNumericMatrix(map->size_pixels, map->size_pixels, + mxUINT8_CLASS, mxREAL); + + pointer = (unsigned char *)mxGetPr(plhs[0]); + + map_get(map, pointer); +} + + +static void _scan_init(mxArray *plhs[], const mxArray * prhs[]) +{ + + laser_t * laser = (laser_t *)mxMalloc(sizeof(laser_t)); + + scan_t * scan = (scan_t *)mxMalloc(sizeof(scan_t)); + + int span = (int)mxGetScalar(prhs[2]); + + _rhs2laser(laser, prhs, 1); + + scan_init(scan, laser->scan_size, span); + + + _insert_obj_lhs(plhs, scan, 0); + _insert_obj_lhs(plhs, laser, 1); +} + +static void _scan_disp(const mxArray * prhs[]) +{ + char str[MAXSTR]; + + scan_t * scan = _rhs2scan(prhs, 1); + + scan_string(*scan, str); + + printf("%s\n", str); +} + +static void _scan_update(const mxArray * prhs[]) +{ + scan_t * scan = _rhs2scan(prhs, 1); + + laser_t * laser = (laser_t *)_rhs2ptr(prhs, 2); + + int scansize = (int)mxGetNumberOfElements(prhs[3]); + + int * lidar_mm = (int *)mxGetPr(prhs[3]); + + double hole_width_mm = mxGetScalar(prhs[4]); + + double * velocities = mxGetPr(prhs[5]); + + scan_update(scan, lidar_mm, *laser, hole_width_mm, velocities[0], velocities[1]); +} + +static void _randomizer_init(mxArray *plhs[], const mxArray * prhs[]) +{ + int seed = (int)mxGetScalar(prhs[1]); + + void * r = mxMalloc(random_size()); + + random_init(r, seed); + + _insert_obj_lhs(plhs, r, 0); +} + +static void _rmhcPositionSearch(mxArray *plhs[], const mxArray * prhs[]) +{ + position_t start_pos = _rhs2pos(prhs, 1); + + map_t * map = _rhs2map(prhs, 2); + + scan_t * scan = _rhs2scan(prhs, 3); + + laser_t laser; + position_t new_pos; + + double sigma_xy_mm = mxGetScalar(prhs[5]); + + double sigma_theta_degrees = mxGetScalar(prhs[6]); + + int max_search_iter = (int)mxGetScalar(prhs[7]); + + void * randomizer = (void *)(long)mxGetScalar(prhs[8]); + + _rhs2laser(&laser, prhs, 4); + + new_pos = rmhc_position_search( + start_pos, + map, + scan, + laser, + sigma_xy_mm, + sigma_theta_degrees, + max_search_iter, + randomizer); + + plhs[0] = mxCreateDoubleScalar(new_pos.x_mm); + plhs[1] = mxCreateDoubleScalar(new_pos.y_mm); + plhs[2] = mxCreateDoubleScalar(new_pos.theta_degrees); +} + +/* The gateway function ------------------------------------------------ */ +void mexFunction( int nlhs, mxArray *plhs[], + int nrhs, const mxArray * prhs[]) +{ + + char methodname[MAXSTR]; + + mxGetString(prhs[0], methodname, 100); + + if (_streq(methodname, "Map_init")) + { + _map_init(plhs, prhs); + } + + else if (_streq(methodname, "Map_disp")) + { + _map_disp(prhs); + } + + else if (_streq(methodname, "Map_update")) + { + _map_update(prhs); + } + + else if (_streq(methodname, "Map_get")) + { + _map_get(plhs, prhs); + } + + else if (_streq(methodname, "Scan_init")) + { + _scan_init(plhs, prhs); + } + + else if (_streq(methodname, "Scan_disp")) + { + _scan_disp(prhs); + } + + else if (_streq(methodname, "Scan_update")) + { + _scan_update(prhs); + } + + else if (_streq(methodname, "Randomizer_init")) + { + _randomizer_init(plhs, prhs); + } + + else if (_streq(methodname, "rmhcPositionSearch")) + { + _rmhcPositionSearch(plhs, prhs); + } +} + diff --git a/matlab/mex_breezyslam.mexa64 b/matlab/mex_breezyslam.mexa64 new file mode 100755 index 0000000000000000000000000000000000000000..adaa9db41b8ea51fe555af8fa26eb36e307826c9 GIT binary patch literal 23528 zcmeHv3v^WF+3ucPASyT$1WgrXs)(fn@UN}-_j0gHe)6}X)QU{FB~Y}1wi-nxwc73}iU#TLwI;)$-yx;r0@ArQ1_kP!X$@hS>d_kJUqR1;%isD(_Cc*}VYvH15Ww`E|^BNC4e)PF}`WD@D-aGFf2){B!MNsxU{Fm{!m4NBA zw_k-qM{Yt}sVA_G$Vq$}qt>&7Ju?}Wh#$q?fnNr6*+?W5?gN}(Ty?r8Q`q|l#| z0za6-&bcY{|C~bqrz!ATQrPKCf&VInowX_S|DHns)f70)D0ciGc|D!Neo+ei9vB!c z{(1`iXH(!CQsC9FZy)I-_?i^@tg6CQ@9}$(m$o2O0jwlDMqD*d3P zeotM%vnc5G_?z4nbpd}Zz!EN(DRXnv zGH-ifn@^#HC!PXQcr9VAfkp(kp7l>)+h_h%jTE5 zW)#jSye6KWSvV`6p2d4nI$ITJWlC2PYjs9^O{6tL>WmS(>1>tdYbMFYVCA5-!y^7Y z_HVNkT5l%f|A*+abP-9z@1|Q6CL@gcGhLLg2WdI)2QO|qhpc}Um!~U-g`D&Q-yr!I zGAw>-yqlfrBzE8K;m|R+f+M=6^To}e;&tac*(V# z^af1$1q6s|(1c$sK~TelUuMFOn{e}dF=WE8FzM%%*cmq#zZ8FY*-bdLpSCj1kE+6OIOoUzH~O+&GH)+k~HI!k3zG^H!qKgrmXZSE~sZ zTT>=$H{qgb8Qy8a<=%<}>rA+LUS4m)&FjGi6K-zzjV7GNfxI@E@JSK`?Ka^Tn(%EV z{2~(`HQ_lXyw8Mx!-V&n@JmeifC;CuDz8BkeyIdO4HG`agdaEIb`w5i!oO+46_smI zpECFJEEAp!nY^^FkFvCIrgNrU(L&Kcrg4P@ovmwk)-I{R>F_nTLS;Cw3cuDVB}ft9 zNW$3QFs{6th(~56*3bC)#M97;MHzoR@ib&&-He|>JPq~OM#fJio`z0rJ>xGYo`y`U zlkpc5Pt}UGGJXQ_G(=)c8GkPEG&EwBj87w;hD5A{@&A|so`yoKi18);)a7Few_Hpuw>#8cOf^)r4a@e_!TGX7=aFCe~~ z@xLOTx^QeG<9|s!b=}x{#{WC<)MaCxjQ=;{sjJ3X8UH_tr!E>>%J_$fr>+^RWc>Gu zr>QYk!ub1$r!E>RV!WSt>Y6b-rqIP(Y`UmuDLYp1zF}vZ?epX z0w-!Ueedx5l)rQC=hN+q68x6dHFpQZC{q70Fis24Jp|mSKnoa+_^I8S*$=>Sa#sUg zh1Mx+;WBmMxg~|j7Pu15`Gj*9SHu6QfMIL6zczLo3|Oahl78%Fq^S(eeOe3OaK`v8 zRXVKH?jlgFTCC|OHTR+NNbZ}zA^n%BXS_A>}quQOI}IYAUGfBb%mw!3%psi(GRMjZhZ8A=h{XE}pPv zI|s_c!2t-iOTkYQ0xt=klY)mJDA#9}>vv}%V=3$oU~JpqjasYTX{wv4xcg*git!2S zw5XmAlPwaxj+a%M1+YPamkZDaut|dB1(*ZSE5RYeh8Zoj170rSKQlPHG(R3FCF z#YXoR)PJwZKw;(jC&o|U7pA(qwDA2|#wo}Unov9P0I(T<5kM<|^6+LNJM7e850Mpp z7o6Wp%H{fIA}6dio)=B|Bxa|Vp$bplE7$*K>_pSXuECV1MYfYq@Il7_GcM&0+{U^O z^^&#J7a~8Vc}xqVktXJ9;mRycugb;TTnV5m*QSL_ax~qMi=QJ#FG@lo=*=n&Zlf}d zo8Vup7ZYltw0tUU3ra>D*XmG;mpB0>mg&1+rTLi*rZIjGvPPl)GELL4Z+OVD@cnk< zwSOdqDc^X70n;AmaSKr{jktg5jA|B zT0u>6Wd|l*qky~OkJoTLx&Oay^GY;#71}&pX{Ur8iF``rqdOE)cfijP;~LbTcZV4$ zi+6`Ps8nnl+Se2la%3YPR%=Ns?o2wIL1^OL;UtUmZbT=?I0Qp1@mxG)c4PZcB4p*^ z?PB!g8zB}-TV+;R7@Zg$xhzbb7#;(mUW}BDQoLT2;uWJ5uNg*ER=Lhh%E85A{fV&( zt9OiUdJ_qmt=ez z8E<9At!uqpM030BBgO*ciN|aQ3(uZc`PeyPY>9^}-*^P&%N__9)bBAR>A49XJqCl066lZbIsvDfe`vWteuXY(0 zhyHfKeuo})6!clQ>~xwkI`pwD%h7Sp2L5xzLlx{Z$hg^`8|U@INGTGQXsB9s1s zEgK(a;mqN0*%d83n-9>NpvU(PMUDAm$|NwYG4r^$GHhV6&n#Gj~yvbcX;7s z%;}GO3@=puGgW^>)qfwZu;~>~Lnm`bj-oVJZ`*ysx+HTK(qv)1`U=%ri&XS!dc``> zC}^j?6VdsT!}9(K>(u?wujsaJaXyVGfRCQA-q}Y5Z)>pT_dw``2Q|+1WH!Le-pQyI z4t8qcj&;TlPO)xKjf}R6z7wi->R!#g7#*?H=Fo3g&(rD1-VcS^ZAjFjVt4!jWlZcB zn&=5jP*!$Ee^+UaMeW*c371ZG6c1V-y@i&?uH7}J)~8m7OPTK>$i`c&^l4(Vpt*;& zp1-9TOVO!BT$A=!s(y;Xg1wY?K-Et>tXoc(xxdyd!$u);XnMLcbb7U2?K)<;IZ}RY z8f!Bxd_hBRM%u9lw618HR@@gn=Fr`ktnRi^U3Zu3-T|sPewK`P!zILzs#2PB)}~7f z&oh2=LVD&1J9CiHX?N;9T4cO|y8x|sC#pNldJgMl#$Bl1$PTjRqfKbjG98omDg6)n z<2A^F0z156;j%p&ps?Hc zEtX|HR1c#h+(_Mf9R$t|#B=csu@3@W3NFTgab=Hg?B-CXX}8k*xS?J=gTjaoyGVhd4RyVe?c5Q#8rSRo0Lgl$@_ktU>7 zeIOj6h7VV-)xuj@lZLlba~gMIrNVp_nlIEU)`lM^O{kGv3vVZF<2s>s3Dlgr5$;&4 z77Sq~?ire*PLHYuQAfC9lSAJh-b$GZPU!uROy60sGhESE@VVYcT#u^nSAjSW6dc!k zdOn{ry|19pQT$1X_37Rc>x;vYRr3(M!|IvCj^fuH*7Cz@asTR^aD@7Rqadd5@A=1+ z=?7K)HMQVRM+?GRsRvvY+@ya>re3GXw%|4WbBBIJ)qm&Ep}14;Q}upl=;Pp2O!rl| zC zDpmb>nfnh~WYz>t-#Qz4HTMzCa`;uU&2~Tzy?0?`a=t^a-KhSSo+e{H>U0+Da_GTM zRsS06dl7PBn@5?;^`8@Q>bo7qCsr5Esowa&Md`r}j&v45XYp$t7h}$J7Q~KDxC-!9 z3|={=>)0@=<*>e_IIUY?`ES-OUpp+lJ;PZI`s~oY)mi11q4bJPN5`Z`DB@i^EvS>D z_|WR799UgYHg|!Qt#<9TIEw?hIo8l0XcxU^H_d`0mWA-bEbEqND7xCtr*3z@7PeYn zEWgFFZrp`kQA_wX$PX3oeBeVqsmArM;=4lkPUtr{tgmK_X>jNnDserzY8E`>s>S^e zyq&zT=wGP%pR8L>U}-6LpDye9YdYOA9Kj9_%Lyg_$daX5sJ>By?V+aA!g%-O-cqcl ziqcz3_bCe2yo?I>2W34Uq|qJ5Gdz=>(m&*Bx=T*nz{{Nnttp<5V3oGPckqPGSj-c4 z<0hWSH&jX_wi{^d5{#>SX92A}f5a26q_u}UGLC(G_S(ZYCuRB>%u-HF8#Yznt20(RNU_+S%v=MKDs$LSv`U z8xnU%(siv~B~5*5fBcH6m$MLfS#n zYUIwY?k?AZ+sgHhe^$%zRthGTObV@W5!JJJ&+3d&bmbV@Eg!uM^EG)~u5T3;sU_P# zrWFc1@P4=vEuu8lv-!SOwJhBg3wb8tJL3-m$Js{|x)!KJ0^|u#ovnc7rPR!9NFM zME^!U*h+J-?HWWFJkUe;180Eq_JQ+ugF6l`Xah&>yM(szxXp5ggE`ya^)Ty(8EBr0 zaEI-;a82nAtpZLdt=HK}RPDOq8O0jvMzSpIR8Z(d?0211v&jQ6m)L4=V|zS6wY2-B zt!PCz_Pf}A)?^OiEr)TKoOW2J!C|o%hn(H4+33b`2~BsjTdm3bPf~v#>dw#y?YQfA zt_zoBsl~fHreSXF4;^aHE#BE-$E~kw*^PCG6!0K?zV)SyrJBXr*~MyM(Ykh7)Z+K7 zk5UtbBUH1{zQ6=%cWOO@=W6bK+Edz@&vB0o3C%i%Ifn34 zaa@Z$%FVvS%)&YunTsd0)`?N;_t3mcoM_A%=g>a(xZk+!Lpiz0#g&(PCCdFx6s?6~ z@dW0i_Ve(C`bAZqo*T;m%GNf{WM8<|M?0Fv|5sk#nY?=NwZvV>kKlP4%x>CERcOlKs zN^hFyTjA-w-~SR5&Avq|ruU-Co%4DhB>w%JW5ujTqOV+i0`JfeC3frT9Kd6P%uXQ2 zoDbL_7=M_F@1&br+CS1OGMLZU>e)@3{Vu8{4{^ECv;;{gK;#A=r8H>4Nm_ykesH`p1!oBl= zp<6xNEq)6%fn@wAcz`4-jF>zt&_6SD38sfzaBG@fiy##qzW;oLsK@AF(ad(DrnYJb z=>GXmCt1$?K4n9|qAXzWh)c2W;P!SJ-S5W(Xi#*XpFBj4CoC<=bV64I@HnZwa4D(C z0Ak){0jwT~T`^h!>6KIXBK=^`pT|!>h}$S5dwLJZU?zw)l97E99k$Opai8^j`zSE@ z2o;dEfaR zW*to2ebg=DT^`HJf!I^9pz80K&CiGZjm$n-y9L%xmg1SnFS?Fe(8{)nKRIc=;~<>a zc@j@LSOc-17d?rnAHYan5uf6Wy9cQg6*{B$&LUgSk!MsVEi&$LnlGqs)-JjmH#>mx zvsn4eB0?r_J?Pmhd*+%PHq1nyX?n1`On;MwZa#`p_1*feuD?8>58y$_RE#9s_+yx& z8mv`4YPc#yoqy_n+F-B9L8Yc*=Nn{!eUJyX3LP0C4gC;K9z8#FxWPKbfr&fR1)grI z=HO|Fi19_JBMm7ZGtXw6K^XBIAiWEqXM~`Es(21q^A8|y6r)?AjPOORg+2Z)SP~z& z5DJ;}&_t5uT4ldzZwrxuwQf(HrFYg5|X zb@-@~K89o|KfZW$HQuMxdjcNzouaF*WqGqFu3nFC9qU@$9#@MGnACw)6I173-qfP_ z8XDR>0V=SfuGQ7lf=>=90Ryc{Ufa2h3AWawJeFMU2`KoMv4v~06jNm>p?7OtOTEtv zU;SLm?`?Ef`r4Z4d&-N0npnciOfCpvbqN>{G+Vkq| z?ex>y)b43+v#%nk!R|$k{B5L$?%u;R5?D6<10$wecpU~-V%FW+4Xr9*XJ#^=e05!emd6{s=n>3 z3*OpyS;-S=H@~v>>QFCH$O z^(O4RwsHO9sZSna1Bc6$PC*&Lyh_&t68p>IJEHhsV!0%J4*dBzgo z!<#_=9hClF;v>-GpkpxvZ5Vv3L1%+bIx;-G6qLqkC#Z(KWjE*^(0))WcB@06H)5}! zkEx*=R0CZON?&4~1YHkmF^~_m2$cTrqZ&_pXuli+wSz`MOF-uxLq5>epzA=N2i*kP zd3<PyrJ%DwJ3&kE^lKC7nj!cJnukYd$3Yi>+OQ{~m(R07>DvVQQtT1TmK#9nlHUqi z?z>g7wA(C~j2oM^9x=^@j6Q<0zXcx=V6FXLGKc?-ggsr zo(KL3RzW3(R_pxW+VK zlM#oFkh5>w*$&=x+elV}sUVwwKn-@D3qlqJe3hrA5(Z=3Dh#pP75X2@$G&qLpi zms4q~mo1YkLrmp84gHGP@Nf~*as9g!<-G!VE#z~|@)cZ8^?C>LcF5V}BK=($?=Nkn zN#$fcR)_{kJsBAryrzoWr(T#-O#@ZbIy-am9Hn4e+v3fd@?+YXF3V{3%E(D@5Btu zC6MQt1O|$6ZM>oe)>G*cr7Pk(Dg z*Emk%f6q&QctF>2w)iT_H#i&r`)syX1V(#Jy6|ZtyX4`fvJsMIkfiTVmG6pQv}b}Oz>LQOG5Lhi4{c3WY4G-z(5FL!ZC zyiYhN{T$$8MX1Hg!`7YoUnCUq@P_fSTs+fYJo^g}*ucG2k{rtv;|E2-xHVvWydI+5 z|5rr*-TcV%_ll13hM<2H^t7O3L`S($&?^PKR?r24epk>2L01U+prB6(`U^o{6m+kk zZwUHVK~D=hhHZ)!=dWCU~ zb#0AGVg1S$sIS)y?No1sQNk`_F^HB*fQjz)Pye6rf$DqP4Q9a2j8d5Z8$oz7ikaUsI zl>SRSNvk2JIZ5(zo|2U6N7qRIIm(|E&>SZ7%Xv)Fr9v@PetIe>Wuz+SRY~Q%D*YcB zKe~4}=a=)eq;g)T{M1e(^Zx)C#Z;~%@>~i@<@y8_c2Qa8>-%8L`MbsZCTYB3MJC$_ z8X1{i%p>yrlzDcMVMIQO{tyXs`EuQrRIW!-f29BPvWD`@_EWwsGzHC)ffum!U$Dxv zNSO1FJm-X-37W5w30zjY?pmb6MXj4&eGPuiqc7Zft-ru;i@dH%^r{gM10nX!EMK<65#%+O zFaQ3$pWSrgSt#V@OXipK0|?Fel@dEwFX6;SLenMlN%}El=KON~v#C6j)RQJg@+To6 zOxEA7+QDJJCh}{HOZ?aqNtPPIFO@&Co-%*#2z}C}OH%yxOuTF+5I;AF@-0$P;3HUO zCq8ye20F_)vsBCnw6AsHzpTHU|7m>6y7L_TcaSD#Tv;Rf|H$&W*66?K@J_CSW{q@= zcDcSK(d@TP)x)5X`jv)g4GbVjRJFL1K+xUj?CnE>k-_%8*{-Vp#B6!z|DeF1WGMD@0>6|dC|nnCqKrYsNAoiqIN7NbH>~WP2J&1e@Ye(`{k&Y@7m108 zy}N+^bb&7rO)s)3#lS}^w=4yIYYMy;IJIMmYDZ~!=f{5ed_0={7N&1gqQyc{5IW~; zwEjlo(d?{)K8v%R8=(G27rnb7ymkubCzGlzAp9^q&xpED?703;YWae>ptOfgRp1p!0As|EThaD`9l93u|fVeH>b=L_(D4eq(5^7 z{`Hj{r@c5`Wdffq?67xDz^kPFZ!tA?<{YJ#3j8U7OFQ(gik|W`s&-1muX}`kt%xUk zrv~Z$0>44jm%TFpzE0Q~+3t@CeSIo7{WDR*j|5&L{80t|oWKhOF0v^v0Jn@XpKllX zSBv)grm(Y5;1SW^*t;{x4hsBd!oH0Ey8_=mjT>O^2$1|h;Oj2uxNMhCfm8dAtnXJ0 zKYJay0Gk!+Cq5C+hq*arvcLz0KXSgxXZYFcb)nFI!Ojh^cX3EwFYuGXj@&1e0+($k zie#iZ1>OwYZdMfObt&|pN`e1p3Y^~Ijpol_3jBBqJQExH(d?X`0>3l`K0O6KKLx%h z1->)|epd>7HSp2m97&=7ObYzhz_Ul$SG<%${~*K9KF{vm6#Ac}z|X;RK?+!2eeYd^>P4)RRWRTfoJZA_@OEg&oE153~h>IFZJU zgY0f9z13A-wzvuh1t!i2bOpRF9B9{quioV0fF{W0s`t5;H~W^=HM{BqK7X65F4(T% z31Dk8z6z@^yteqd8L&Kx5}ha5#Gfp>@U+ms636M$v&j0O*Siu~OdR`eElD-$$UC_1 zZ)}^le5gpPa(7c(8!~$8J@pFA(9wkS8KA3G zdn4@zfagJp&zz+Ug>}Kb6(n*&ir14WZ(R*-~XR>s};iMGKWCcD3 zlQBBkQXb|x>M5h~vqI_2&E&l1(>4(01DAjhflTO*upUG-;GH5cAbaH4y vL?y9qAZOB~16bu5s&s~EA`kh&BxfCI>PkA6H8}@A!8935I;k`vBB%Zf=XOab literal 0 HcmV?d00001 diff --git a/matlab/mex_breezyslam.mexmaci64 b/matlab/mex_breezyslam.mexmaci64 new file mode 100644 index 0000000000000000000000000000000000000000..97fc14b98362a43e56b32a23d6f4d933e4b04536 GIT binary patch literal 23440 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 literal 0 HcmV?d00001 diff --git a/matlab/mex_breezyslam.mexw64 b/matlab/mex_breezyslam.mexw64 new file mode 100644 index 0000000000000000000000000000000000000000..28bdc0a3788bb8904aa184b6dfab3d2f8c9fa44b GIT binary patch literal 18432 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 AaR2}S literal 0 HcmV?d00001