Өнгөрсөн жил роботоор оффис цэвэрлүүлдэг төсөл дээр ажиллав. Тоос сорогч чирсэн (200 мянган евроны үнэтэй) хүн шиг том робот оффисийн өрөө болгоноор шагайгаад шал хаагуур халтар байгааг камер ашиглаж computer vision-ы тусламжтайгаар тогтооно. Хэдэн зуун өрөөтэй оффис цэвэрлэх тул цаг болон мөнгөө хэмнэж зөвхөн тэр халтар болсон хэсгийн л тоосыг нь сорно. Тоос сорсныхоо дараа цэвэрхэн болсон эсэхийг шалгана. Хэрвээ хэд хэдэн удаа тоос сорсон ч гэсэн цэвэрхэн болохгүй бол 3D scanner-аар тэр бохирдсон хэсгийг хэмжинэ. Энэ хэмжилтийнхээ тусламжтайгаар зүгээр будаг болсон толбо уу эсвэл бохь наалдсан овойж товойсон бохирдолт уу гэх мэтээр ангилаад мэдээллийн сан руу хийнэ. Сүүлд нь 7 хоногт нэг удаа ч юм уу цэвэрлэгч ирээд тэр мэдээллийн сан дээр хадгалагдсан арилдаггүй толбуудыг арилгана.
Надаа 3D scanner-аар хэмжилт хийх ажил нь оногдов. Цаанаас нь
Shapescan3D хэмээх scanner өгөв. Зөвхөн Windows дээр ашиглаж болдог эд аж. API гээд нэг header файл болон DLL library дагаж ирсэн байлаа. Бид нар робот програмчлахдаа
Robot Operating System (ROS) гэж middleware ашигладаг, тэр нь зөвхөн Ubuntu дээр л ажиллана. Тэгээд scanner-аа Ubuntu дээр хэрхэн ажиллуулах вэ гэж баахан толгойгоо гашилгав.
IDA ашиглаж dissassemble хийж үзсэн болов ч туршлага дутаад олигтой амжилт олсонгүй.
Wireshark ашиглаж scanner болон компьютер хоорондох communication-ийг чагнаж үзэв. Binary protocol ашиглаж байсан учир бас л сүртэй амжилт гаргасангүй.
Тэгээд аргаа бараад
Wine ашиглахаар шийдэв. Урьд нь Wine ашиглаж Windows программ ажилуулж үзэж байснаас өөрөө программ бичиж DLL library дуудаж үзэж байгаагүй тул болох эсэхийг нь сайн мэдэхгүй байв. Scanner-дагаж A3DSensor.dll болон A3DSenshor.h гэж файлууд дагаж ирсний header нь иймэрхүү функцүүдтэй:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Returns the version of the library
A3D_API INT32 __cdecl A3DLibraryVersion(INT32 *version);
/// Returns the version of the supported protocol version
A3D_API INT32 __cdecl A3DProtocolVersion(INT32 *version);
/// Returns the count of 3d sensors in the local network
A3D_API INT32 __cdecl A3DGetDeviceKeyListSize(INT32 *list_size);
/// Returns the Devicekey for a 3d kit. Before calling this function,
/// A3DGetDeviceKeyListSize must have been called
A3D_API INT32 __cdecl A3DGetDeviceKeyListEntry(INT32 index, A3DDeviceKey *device_key);
/// This function establishes the connection to an individual 3d sensor
A3D_API INT32 __cdecl A3DDevAlloc(const char *ipaddr, A3D_ID_PTR devicePointer);
...
Энэ функцуудыг Wine ашиглаад Linux программаас дуудчихвал хамаг юм болчих гээд байлаа. Интернэтээс олсон
энэ зааврын дагуу хийж үзэхээр шийдэв. Санасныг бодоход хялбар юм байна. DLL файлаа
LoadLibrary method ашиглаж санах ойруу хуулаад
GetProcAddress method-ын тусламжтайгаар дуудах гэж байгаа method-уудыхаа хаягийг олдог аж. DLL library-гаа ашиглаж дууссаныхаа дараа
FreeLibray method ашиглаж санах ойноосоо буцааж устгана. Энэ гурван method гурвуулаа Windows-API.
Хамгийн түрүүнд DLL library-аа санах ойд ачааллана:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
HINSTANCE h = LoadLibrary("A3DSensor.dll");
GetProcAddress method ашиглаж байгаа тул дагаж ирсэн header файлыг шууд ашиглаж болохгүй. Тиймээс бүх method-уудаа бага зэрэг өөрчлөөд дахиж шинээр зарлана. Жишээ нь
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Returns the version of the library
A3D_API INT32 __cdecl A3DLibraryVersion(INT32 *version);
гэсэн method-ыг доорх байдлаар зарлана:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef int (__cdecl * A3DLibraryVersion_FUNC)(int *version);
A3DLibraryVersion_FUNC A3DLibraryVersion;
Дараа нь энэ method-ыхоо хаягийг олох хэрэгтэй:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A3DLibraryVersion = (A3DLibraryVersion_FUNC) GetProcAddress(h, "A3DLibraryVersion");
Ингэснийхээ дараагаар method-уудаа яаг Windows дээр яаж ашиглах ёстой тэрэн шиг нь ашиглах боломжтой болно.
Программ бүтнээрээ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h>
#include <iostream>
int main(int argc, char **argv) {
HINSTANCE h = LoadLibrary("A3DSensor.dll");
typedef int (__cdecl * A3DLibraryVersion_FUNC)(int *version);
A3DLibraryVersion_FUNC A3DLibraryVersion = (A3DLibraryVersion_FUNC) GetProcAddress(h, "A3DLibraryVersion");
int version;
int ret = A3DLibraryVersion(&version);
std::cout<<"Version: "<<version<<std::endl;
FreeLibrary(h);
}
Wine суулгахад
wineg++ ,
winegcc гээд compiler-ууд дагаж ирдэг. Энэ compiler-ыхаа тусламжтайгаар программаа build хийнэ:
wineg++ shapescan3d.cpp
Үүссэн программаа Linux дээр дуудхад ингэж гарч ирж байна:
$ ./a.out
Version: 2500
Яаг энэ аргаар бусад бүх method-уудаа зарлаад scanner-аа 100% Linux дээр ашиглаж болдог болгов. Wine ашигласны нэг сайн чанар нь бичиж байгаа программандаа Linux-API, Windows-API дураараа хольж болдог юм байна. Тэгээд бичсэн программ маань Linux программ гэхэд ч хэцүү Windows программ гэхэд ч хэцүү hybrid юм болвоо хөөрхий :)