36 #include <visp3/core/vpConfig.h>
38 #if defined(VISP_HAVE_NLOHMANN_JSON) && defined(VISP_HAVE_THREADS)
40 #include <visp3/dnn_tracker/vpMegaPose.h>
42 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
43 #include <arpa/inet.h>
45 #include <netinet/in.h>
46 #include <sys/socket.h>
56 using json = nlohmann::json;
65 void encode(std::vector<uint8_t> &)
75 void encode(std::vector<uint8_t> &buffer,
const T &
object) =
delete;
80 void encode(std::vector<uint8_t> &buffer,
const int &
object)
82 const uint32_t v = htonl(
object);
83 const uint8_t *varr = (uint8_t *)&v;
84 buffer.insert(buffer.end(), varr, varr + 4);
88 void encode(std::vector<uint8_t> &buffer,
const float &
object)
90 assert((
sizeof(uint32_t) ==
sizeof(
float)));
91 const uint32_t *pointer =
reinterpret_cast<const uint32_t *
>(&object);
92 const uint32_t v = htonl(*pointer);
93 const uint8_t *varr = (uint8_t *)&v;
94 buffer.insert(buffer.end(), varr, varr + 4);
98 void encode(std::vector<uint8_t> &buffer,
const std::string &
object)
100 const int size =
static_cast<int>(
object.size());
101 encode(buffer, size);
102 const uint8_t *chars = (uint8_t *)&
object[0];
103 buffer.insert(buffer.end(), chars, chars + size);
107 void encode(std::vector<uint8_t> &buffer,
const std::vector<T> &
object)
109 const int size =
static_cast<int>(
object.size());
110 encode(buffer, size);
111 for (
const T &value :
object) {
112 encode(buffer, value);
117 template<
typename T,
typename ...Rest>
118 void encode(std::vector<uint8_t> &buffer,
const T &
object,
const Rest& ...rest)
120 encode(buffer,
object);
121 encode(buffer, rest...);
125 void encode(std::vector<uint8_t> &buffer,
const vpImage<vpRGBa> &
object)
127 const int height =
object.getHeight(), width =
object.getWidth();
128 encode(buffer, height, width, 4);
129 const uint32_t sentSize = height * width * 4;
131 buffer.reserve(buffer.size() + sentSize);
132 const uint8_t *
const bitmap = (uint8_t *)
object.bitmap;
133 buffer.insert(buffer.end(), bitmap, bitmap + sentSize);
140 const int height =
object.getHeight(), width =
object.getWidth();
141 encode(buffer, height, width);
143 const uint16_t hostTest = 1;
144 const uint16_t netTest = htons(hostTest);
145 const uint8_t endianness = hostTest == netTest ?
'>' :
'<';
146 const uint32_t sentSize = height * width * 2;
148 buffer.reserve(buffer.size() + sentSize + 1);
149 buffer.push_back(endianness);
150 const uint8_t *
const bitmap = (uint8_t *)
object.bitmap;
151 buffer.insert(buffer.end(), bitmap, bitmap + sentSize);
157 encode(buffer, (
float)
object.get_px(), (
float)
object.get_py(),
158 (
float)
object.get_u0(), (
float)
object.get_v0());
164 std::vector<float> array;
166 const double *
const data =
object.data;
167 for (
unsigned i = 0; i < 16; ++i) {
168 array.push_back((
float)data[i]);
170 encode(buffer, array);
175 void decode(
const std::vector<uint8_t> &,
unsigned int &)
186 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, T &t) =
delete;
189 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
int &value)
191 const uint8_t *ptr = &buffer[index];
192 value = ntohl(*((uint32_t *)ptr));
193 index +=
sizeof(int);
196 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
float &value)
198 const uint8_t *ptr = &buffer[index];
199 const uint32_t v = ntohl(*((uint32_t *)ptr));
200 memcpy(&value, &v,
sizeof(uint32_t));
201 index +=
sizeof(float);
204 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, std::string &value)
207 decode(buffer, index, size);
209 value.replace(0, size, (
char *)&buffer[index], size);
214 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, std::vector<T> &value)
217 decode(buffer, index, size);
219 for (
int i = 0; i < size; ++i) {
221 decode(buffer, index, t);
227 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
vpHomogeneousMatrix &value)
229 std::vector<float> values;
230 decode(buffer, index, values);
231 assert(values.size() == 16);
232 for (
int i = 0; i < 16; ++i) {
233 value.
data[i] = values[i];
241 template<
typename T,
typename ...Rest>
242 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, T &
object, Rest& ...rest)
244 decode(buffer, index,
object);
245 decode(buffer, index, rest...);
249 void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
vpImage<vpRGBa> &value)
251 int height, width, channels;
252 decode(buffer, index, height, width, channels);
253 value.
resize(height, width);
255 for (
int i = 0; i < height; ++i) {
256 for (
int j = 0; j < width; ++j) {
257 value.
bitmap[i * width + j] =
vpRGBa(buffer[index], buffer[index + 1], buffer[index + 2], 255);
262 else if (channels == 4) {
263 const unsigned copySize = height * width * channels;
264 memcpy((uint8_t *)value.
bitmap, &buffer[index], copySize);
270 #define MEGAPOSE_CODE_SIZE 4
273 if (code != vpMegaPose::ServerMessage::ERR) {
278 decode(buffer, index, message);
282 const std::unordered_map<vpMegaPose::ServerMessage, std::string> vpMegaPose::m_codeMap =
284 {ServerMessage::ERR,
"RERR"},
285 {ServerMessage::OK,
"OKOK"},
286 {ServerMessage::GET_POSE,
"GETP"},
287 {ServerMessage::RET_POSE,
"RETP"},
288 {ServerMessage::SET_INTR,
"INTR"},
289 {ServerMessage::GET_VIZ,
"GETV"},
290 {ServerMessage::RET_VIZ,
"RETV"},
291 {ServerMessage::GET_SCORE,
"GSCO"},
292 {ServerMessage::RET_SCORE,
"RSCO"},
293 {ServerMessage::SET_SO3_GRID_SIZE,
"SO3G"},
294 {ServerMessage::GET_LIST_OBJECTS,
"GLSO"},
295 {ServerMessage::RET_LIST_OBJECTS,
"RLSO"},
296 {ServerMessage::EXIT,
"EXIT"},
301 return m_codeMap.at(messageType);
306 for (
auto it : m_codeMap) {
307 if (it.second == s) {
316 const uint32_t size = htonl(
static_cast<uint32_t
>(data.size()));
317 const std::string code = messageToString(messageType);
318 uint8_t arr[
sizeof(size) + MEGAPOSE_CODE_SIZE];
319 memcpy(arr, (uint8_t *)&size,
sizeof(size));
321 memcpy(arr +
sizeof(size), (uint8_t *)code.c_str(), MEGAPOSE_CODE_SIZE);
323 std::vector<uint8_t> header(arr, arr +
sizeof(size) + MEGAPOSE_CODE_SIZE);
324 data.insert(data.begin(), header.begin(), header.end());
327 std::pair<vpMegaPose::ServerMessage, std::vector<uint8_t>> vpMegaPose::readMessage()
const
330 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
331 size_t readCount = read(m_serverSocket, &size,
sizeof(uint32_t));
333 size_t readCount = recv(m_serverSocket,
reinterpret_cast<char *
>(&size),
sizeof(uint32_t), 0);
335 if (readCount !=
sizeof(uint32_t)) {
340 unsigned char code[MEGAPOSE_CODE_SIZE];
341 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
342 readCount = read(m_serverSocket, code, MEGAPOSE_CODE_SIZE);
344 readCount = recv(m_serverSocket,
reinterpret_cast<char *
>(code), MEGAPOSE_CODE_SIZE, 0);
346 if (readCount != MEGAPOSE_CODE_SIZE) {
350 std::vector<uint8_t> data;
352 unsigned read_size = 4096;
353 unsigned read_total = 0;
354 while (read_total < size) {
355 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
356 int actually_read = read(m_serverSocket, &data[read_total], read_size);
358 int actually_read = recv(m_serverSocket,
reinterpret_cast<char *
>(&data[read_total]), read_size, 0);
360 if (actually_read <= 0) {
363 read_total += actually_read;
365 std::string codeStr(code, code + MEGAPOSE_CODE_SIZE);
367 return std::make_pair(c, data);
374 if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0) {
378 struct sockaddr_in serv_addr;
379 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
380 if ((m_serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
382 if ((m_serverSocket =
static_cast<int>(socket(AF_INET, SOCK_STREAM, 0))) < 0) {
386 serv_addr.sin_family = AF_INET;
387 serv_addr.sin_port = htons(port);
389 if (inet_pton(AF_INET, host.c_str(), &serv_addr.sin_addr) <= 0) {
393 if ((m_fd = connect(m_serverSocket, (
struct sockaddr *)&serv_addr,
sizeof(serv_addr))) < 0) {
401 std::vector<uint8_t> data;
402 makeMessage(ServerMessage::EXIT, data);
403 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
412 std::vector<vpMegaPoseEstimate>
415 const std::vector<vpRect>*
const detections,
const std::vector<vpHomogeneousMatrix>*
const initial_cTos,
416 int refinerIterations)
418 const std::lock_guard<std::mutex> lock(m_mutex);
419 std::vector<uint8_t> data;
422 parametersJson[
"labels"] = labels;
424 if (detections ==
nullptr && initial_cTos ==
nullptr) {
428 if (detections !=
nullptr) {
429 if (detections->size() != labels.size()) {
432 json detectionsJson = json::array();
433 for (
const vpRect &bb : *detections) {
435 to_megapose_json(j, bb);
436 detectionsJson.push_back(j);
438 parametersJson[
"detections"] = detectionsJson;
441 if (initial_cTos !=
nullptr) {
442 if (initial_cTos->size() != labels.size()) {
445 json cToJson = json::array();
448 to_megapose_json(j, cTo);
449 cToJson.push_back(j);
451 parametersJson[
"initial_cTos"] = cToJson;
453 if (refinerIterations >= 0) {
454 parametersJson[
"refiner_iterations"] = refinerIterations;
456 if (depth !=
nullptr) {
457 if (depth_to_m <= 0.0) {
460 parametersJson[
"use_depth"] =
true;
461 parametersJson[
"depth_scale_to_m"] = depth_to_m;
464 parametersJson[
"use_depth"] =
false;
466 encode(data, parametersJson.dump());
467 if (depth !=
nullptr) {
468 encode(data, *depth);
470 makeMessage(ServerMessage::GET_POSE, data);
471 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
475 std::vector<uint8_t> data_result;
476 std::tie(code, data_result) = readMessage();
478 unsigned int index = 0;
479 if (code != ServerMessage::RET_POSE) {
480 handleWrongReturnMessage(code, data_result);
483 decode(data_result, index, jsonStr);
484 json jsonValue = json::parse(jsonStr);
485 std::vector<vpMegaPoseEstimate> result = jsonValue;
490 const std::vector<std::string>&labels,
const std::vector<vpHomogeneousMatrix>&cTos)
492 const std::lock_guard<std::mutex> lock(m_mutex);
493 std::vector<uint8_t> data;
494 if (cTos.size() != labels.size()) {
495 throw vpException(vpException::generalExceptionEnum::badValue,
"The number of poses should be the same as the number of object labels");
499 json cToJson = json::array();
502 to_megapose_json(j, cTo);
503 cToJson.push_back(j);
505 parametersJson[
"cTos"] = cToJson;
506 parametersJson[
"labels"] = labels;
508 encode(data, parametersJson.dump());
509 makeMessage(ServerMessage::GET_SCORE, data);
510 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
513 std::vector<uint8_t> data_result;
514 std::tie(code, data_result) = readMessage();
516 if (code != ServerMessage::RET_SCORE) {
517 handleWrongReturnMessage(code, data_result);
519 unsigned int index = 0;
521 decode(data_result, index, jsonStr);
522 json jsonValue = json::parse(jsonStr);
523 std::vector<double> result = jsonValue;
530 const std::lock_guard<std::mutex> lock(m_mutex);
531 std::vector<uint8_t> data;
534 message[
"px"] = cam.
get_px();
535 message[
"py"] = cam.
get_py();
536 message[
"u0"] = cam.
get_u0();
537 message[
"v0"] = cam.
get_v0();
538 message[
"h"] = height;
539 message[
"w"] = width;
541 encode(data, message.dump());
542 makeMessage(ServerMessage::SET_INTR, data);
544 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
546 std::vector<uint8_t> data_result;
547 std::tie(code, data_result) = readMessage();
548 if (code != ServerMessage::OK) {
549 handleWrongReturnMessage(code, data_result);
554 const std::vector<vpHomogeneousMatrix>&poses,
const std::string& viewType)
556 const std::lock_guard<std::mutex> lock(m_mutex);
557 std::vector<uint8_t> data;
559 j[
"labels"] = objectNames;
560 json cToJson = json::array();
563 to_megapose_json(j, cTo);
564 cToJson.push_back(j);
566 j[
"poses"] = cToJson;
567 j[
"type"] = viewType;
568 encode(data, j.dump());
569 makeMessage(ServerMessage::GET_VIZ, data);
570 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
572 std::vector<uint8_t> data_result;
573 std::tie(code, data_result) = readMessage();
575 if (code != ServerMessage::RET_VIZ) {
576 handleWrongReturnMessage(code, data_result);
579 unsigned int index = 0;
580 decode(data_result, index, result);
586 const std::lock_guard<std::mutex> lock(m_mutex);
587 std::vector<uint8_t> data;
589 j[
"so3_grid_size"] = num;
590 encode(data, j.dump());
591 makeMessage(ServerMessage::SET_SO3_GRID_SIZE, data);
592 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
594 std::vector<uint8_t> data_result;
595 std::tie(code, data_result) = readMessage();
596 if (code != ServerMessage::OK) {
597 handleWrongReturnMessage(code, data_result);
603 const std::lock_guard<std::mutex> lock(m_mutex);
604 std::vector<uint8_t> data;
605 makeMessage(ServerMessage::GET_LIST_OBJECTS, data);
606 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
608 std::vector<uint8_t> data_result;
609 std::tie(code, data_result) = readMessage();
610 if (code != ServerMessage::RET_LIST_OBJECTS) {
611 handleWrongReturnMessage(code, data_result);
613 unsigned int index = 0;
615 decode(data_result, index, jsonStr);
616 json jsonValue = json::parse(jsonStr);
617 std::vector<std::string> result = jsonValue;
624 class VISP_EXPORT dummy_vpMegaPose
627 dummy_vpMegaPose() { };
630 #if !defined(VISP_BUILD_SHARED_LIBS)
632 void dummy_vpMegaPose_fct() { };
Type * data
Address of the first element of the data array.
Generic class defining intrinsic camera parameters.
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
Implementation of an homogeneous matrix and operations on such kind of matrices.
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Type * bitmap
points toward the bitmap
void setIntrinsics(const vpCameraParameters &cam, unsigned height, unsigned width)
vpImage< vpRGBa > viewObjects(const std::vector< std::string > &objectNames, const std::vector< vpHomogeneousMatrix > &poses, const std::string &viewType)
std::vector< vpMegaPoseEstimate > estimatePoses(const vpImage< vpRGBa > &image, const std::vector< std::string > &objectNames, const vpImage< uint16_t > *const depth=nullptr, const double depthToM=0.f, const std::vector< vpRect > *const detections=nullptr, const std::vector< vpHomogeneousMatrix > *const initial_cTos=nullptr, int refinerIterations=-1)
std::vector< std::string > getObjectNames()
Query the server to find the name of all of the objects it knows.
void setCoarseNumSamples(const unsigned num)
std::vector< double > scorePoses(const vpImage< vpRGBa > &image, const std::vector< std::string > &objectNames, const std::vector< vpHomogeneousMatrix > &cTos)
vpMegaPose(const std::string &host, int port, const vpCameraParameters &cam, unsigned height, unsigned width)
Defines a rectangle in the plane.