34#include <visp3/core/vpConfig.h>
36#if defined(VISP_HAVE_NLOHMANN_JSON) && defined(VISP_HAVE_THREADS)
38#include <visp3/dnn_tracker/vpMegaPose.h>
40#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
43#include <netinet/in.h>
44#include <sys/socket.h>
51# pragma clang diagnostic push
52# pragma clang diagnostic ignored "-Wnonportable-system-include-path"
58# pragma clang diagnostic pop
66using json = nlohmann::json;
75void encode(std::vector<uint8_t> &)
85void encode(std::vector<uint8_t> &buffer,
const T &
object) =
delete;
90void encode(std::vector<uint8_t> &buffer,
const int &
object)
92 const uint32_t
v = htonl(
object);
93 const uint8_t *varr = (uint8_t *)&v;
94 buffer.insert(buffer.end(), varr, varr + 4);
98void encode(std::vector<uint8_t> &buffer,
const float &
object)
100 assert((
sizeof(uint32_t) ==
sizeof(
float)));
101 const uint32_t *pointer =
reinterpret_cast<const uint32_t *
>(&object);
102 const uint32_t
v = htonl(*pointer);
103 const uint8_t *varr = (uint8_t *)&v;
104 buffer.insert(buffer.end(), varr, varr + 4);
108void encode(std::vector<uint8_t> &buffer,
const std::string &
object)
110 const int size =
static_cast<int>(
object.size());
111 encode(buffer, size);
112 const uint8_t *chars = (uint8_t *)&
object[0];
113 buffer.insert(buffer.end(), chars, chars + size);
117void encode(std::vector<uint8_t> &buffer,
const std::vector<T> &
object)
119 const int size =
static_cast<int>(
object.size());
120 encode(buffer, size);
121 for (
const T &value :
object) {
122 encode(buffer, value);
127template<
typename T,
typename ...Rest>
128void encode(std::vector<uint8_t> &buffer,
const T &
object,
const Rest& ...rest)
130 encode(buffer,
object);
131 encode(buffer, rest...);
135void encode(std::vector<uint8_t> &buffer,
const vpImage<vpRGBa> &
object)
137 const int height =
object.getHeight(),
width =
object.getWidth();
138 encode(buffer, height, width, 4);
141 buffer.reserve(buffer.size() + sentSize);
142 const uint8_t *
const bitmap = (uint8_t *)
object.bitmap;
143 buffer.insert(buffer.end(), bitmap, bitmap + sentSize);
150 const int height =
object.getHeight(),
width =
object.getWidth();
151 encode(buffer, height, width);
153 const uint16_t hostTest = 1;
154 const uint16_t netTest = htons(hostTest);
155 const uint8_t endianness = hostTest == netTest ?
'>' :
'<';
158 buffer.reserve(buffer.size() + sentSize + 1);
159 buffer.push_back(endianness);
160 const uint8_t *
const bitmap = (uint8_t *)
object.bitmap;
161 buffer.insert(buffer.end(), bitmap, bitmap + sentSize);
167 encode(buffer,
static_cast<float>(
object.get_px()),
static_cast<float>(
object.get_py()),
168 static_cast<float>(
object.get_u0()),
static_cast<float>(
object.get_v0()));
174 std::vector<float> array;
176 const double *
const data =
object.data;
177 for (
unsigned i = 0;
i < 16; ++
i) {
178 array.push_back(
static_cast<float>(data[i]));
180 encode(buffer, array);
185void decode(
const std::vector<uint8_t> &,
unsigned int &)
196void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, T &t) =
delete;
199void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
int &value)
201 const uint8_t *ptr = &buffer[index];
202 value = ntohl(*((uint32_t *)ptr));
203 index +=
sizeof(
int);
206void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
float &value)
208 const uint8_t *ptr = &buffer[index];
209 const uint32_t
v = ntohl(*((uint32_t *)ptr));
210 memcpy(&value, &v,
sizeof(uint32_t));
211 index +=
sizeof(float);
214void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, std::string &value)
217 decode(buffer, index, size);
219 value.replace(0, size, (
char *)&buffer[index], size);
224void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, std::vector<T> &value)
227 decode(buffer, index, size);
229 for (
int i = 0;
i < size; ++
i) {
231 decode(buffer, index, t);
237void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
vpHomogeneousMatrix &value)
239 std::vector<float> values;
240 decode(buffer, index, values);
241 assert(values.size() == 16);
242 for (
int i = 0;
i < 16; ++
i) {
243 value.
data[
i] = values[
i];
251template<
typename T,
typename ...Rest>
252void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index, T &
object, Rest& ...rest)
254 decode(buffer, index,
object);
255 decode(buffer, index, rest...);
259void decode(
const std::vector<uint8_t> &buffer,
unsigned int &index,
vpImage<vpRGBa> &value)
262 decode(buffer, index, height, width, channels);
263 value.
resize(height, width);
266 for (
int j = 0;
j <
width; ++
j) {
267 value.
bitmap[
i *
width +
j] =
vpRGBa(buffer[index], buffer[index + 1], buffer[index + 2], 255);
272 else if (channels == 4) {
273 const unsigned copySize =
height *
width * channels;
274 memcpy((uint8_t *)value.
bitmap, &buffer[index], copySize);
280#define MEGAPOSE_CODE_SIZE 4
288 decode(buffer, index, message);
292const std::unordered_map<vpMegaPose::ServerMessage, std::string> vpMegaPose::m_codeMap =
294 {ServerMessage::ERR,
"RERR"},
295 {ServerMessage::OK,
"OKOK"},
296 {ServerMessage::GET_POSE,
"GETP"},
297 {ServerMessage::RET_POSE,
"RETP"},
298 {ServerMessage::SET_INTR,
"INTR"},
299 {ServerMessage::GET_VIZ,
"GETV"},
300 {ServerMessage::RET_VIZ,
"RETV"},
301 {ServerMessage::GET_SCORE,
"GSCO"},
302 {ServerMessage::RET_SCORE,
"RSCO"},
303 {ServerMessage::SET_SO3_GRID_SIZE,
"SO3G"},
304 {ServerMessage::GET_LIST_OBJECTS,
"GLSO"},
305 {ServerMessage::RET_LIST_OBJECTS,
"RLSO"},
306 {ServerMessage::EXIT,
"EXIT"},
311 return m_codeMap.at(messageType);
316 for (
auto it : m_codeMap) {
317 if (it.second == s) {
326 const uint32_t size = htonl(
static_cast<uint32_t
>(
data.size()));
327 const std::string code = messageToString(messageType);
328 uint8_t arr[
sizeof(size) + MEGAPOSE_CODE_SIZE];
329 memcpy(arr, (uint8_t *)&size,
sizeof(size));
331 memcpy(arr +
sizeof(size), (uint8_t *)code.c_str(), MEGAPOSE_CODE_SIZE);
333 std::vector<uint8_t> header(arr, arr +
sizeof(size) + MEGAPOSE_CODE_SIZE);
334 data.insert(
data.begin(), header.begin(), header.end());
337std::pair<vpMegaPose::ServerMessage, std::vector<uint8_t>> vpMegaPose::readMessage()
const
340#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
341 size_t readCount = read(m_serverSocket, &size,
sizeof(uint32_t));
343 size_t readCount = recv(m_serverSocket,
reinterpret_cast<char *
>(&size),
sizeof(uint32_t), 0);
345 if (readCount !=
sizeof(uint32_t)) {
350 unsigned char code[MEGAPOSE_CODE_SIZE];
351#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
352 readCount = read(m_serverSocket, code, MEGAPOSE_CODE_SIZE);
354 readCount = recv(m_serverSocket,
reinterpret_cast<char *
>(code), MEGAPOSE_CODE_SIZE, 0);
356 if (readCount != MEGAPOSE_CODE_SIZE) {
360 std::vector<uint8_t>
data;
362 unsigned read_size = 4096;
363 unsigned read_total = 0;
364 while (read_total < size) {
365#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
366 int actually_read = read(m_serverSocket, &data[read_total], read_size);
368 int actually_read = recv(m_serverSocket,
reinterpret_cast<char *
>(&data[read_total]), read_size, 0);
370 if (actually_read <= 0) {
373 read_total += actually_read;
375 std::string codeStr(code, code + MEGAPOSE_CODE_SIZE);
377 return std::make_pair(c, data);
384 if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0) {
388 struct sockaddr_in serv_addr;
389#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
390 if ((m_serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
392 if ((m_serverSocket =
static_cast<int>(socket(AF_INET, SOCK_STREAM, 0))) < 0) {
396 serv_addr.sin_family = AF_INET;
397 serv_addr.sin_port = htons(port);
399 if (inet_pton(AF_INET, host.c_str(), &serv_addr.sin_addr) <= 0) {
403 if ((m_fd = connect(m_serverSocket, (
struct sockaddr *)&serv_addr,
sizeof(serv_addr))) < 0) {
411 std::vector<uint8_t> data;
413 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
422std::vector<vpMegaPoseEstimate>
425 const std::vector<vpRect>*
const detections,
const std::vector<vpHomogeneousMatrix>*
const initial_cTos,
426 int refinerIterations)
428 const std::lock_guard<std::mutex> lock(m_mutex);
429 std::vector<uint8_t> data;
432 parametersJson[
"labels"] = labels;
434 if (detections ==
nullptr && initial_cTos ==
nullptr) {
438 if (detections !=
nullptr) {
439 if (detections->size() != labels.size()) {
442 json detectionsJson = json::array();
443 for (
const vpRect &bb : *detections) {
445 to_megapose_json(j, bb);
446 detectionsJson.push_back(j);
448 parametersJson[
"detections"] = detectionsJson;
451 if (initial_cTos !=
nullptr) {
452 if (initial_cTos->size() != labels.size()) {
455 json cToJson = json::array();
458 to_megapose_json(j, cTo);
459 cToJson.push_back(j);
461 parametersJson[
"initial_cTos"] = cToJson;
463 if (refinerIterations >= 0) {
464 parametersJson[
"refiner_iterations"] = refinerIterations;
466 if (depth !=
nullptr) {
467 if (depth_to_m <= 0.0) {
470 parametersJson[
"use_depth"] =
true;
471 parametersJson[
"depth_scale_to_m"] = depth_to_m;
474 parametersJson[
"use_depth"] =
false;
476 encode(data, parametersJson.dump());
477 if (depth !=
nullptr) {
478 encode(data, *depth);
481 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
485 std::vector<uint8_t> data_result;
486 std::tie(code, data_result) = readMessage();
488 unsigned int index = 0;
490 handleWrongReturnMessage(code, data_result);
493 decode(data_result, index, jsonStr);
494 json jsonValue = json::parse(jsonStr);
495 std::vector<vpMegaPoseEstimate> result = jsonValue;
500 const std::vector<std::string>&labels,
const std::vector<vpHomogeneousMatrix>&cTos)
502 const std::lock_guard<std::mutex> lock(m_mutex);
503 std::vector<uint8_t> data;
504 if (cTos.size() != labels.size()) {
509 json cToJson = json::array();
512 to_megapose_json(j, cTo);
513 cToJson.push_back(j);
515 parametersJson[
"cTos"] = cToJson;
516 parametersJson[
"labels"] = labels;
518 encode(data, parametersJson.dump());
520 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
523 std::vector<uint8_t> data_result;
524 std::tie(code, data_result) = readMessage();
527 handleWrongReturnMessage(code, data_result);
529 unsigned int index = 0;
531 decode(data_result, index, jsonStr);
532 json jsonValue = json::parse(jsonStr);
533 std::vector<double> result = jsonValue;
540 const std::lock_guard<std::mutex> lock(m_mutex);
541 std::vector<uint8_t> data;
544 message[
"px"] = cam.get_px();
545 message[
"py"] = cam.get_py();
546 message[
"u0"] = cam.get_u0();
547 message[
"v0"] = cam.get_v0();
548 message[
"h"] = height;
549 message[
"w"] = width;
551 encode(data, message.dump());
554 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
556 std::vector<uint8_t> data_result;
557 std::tie(code, data_result) = readMessage();
559 handleWrongReturnMessage(code, data_result);
564 const std::vector<vpHomogeneousMatrix>&poses,
const std::string& viewType)
566 const std::lock_guard<std::mutex> lock(m_mutex);
567 std::vector<uint8_t> data;
569 j[
"labels"] = objectNames;
570 json cToJson = json::array();
573 to_megapose_json(j, cTo);
574 cToJson.push_back(j);
576 j[
"poses"] = cToJson;
577 j[
"type"] = viewType;
578 encode(data, j.dump());
580 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
582 std::vector<uint8_t> data_result;
583 std::tie(code, data_result) = readMessage();
586 handleWrongReturnMessage(code, data_result);
589 unsigned int index = 0;
590 decode(data_result, index, result);
596 const std::lock_guard<std::mutex> lock(m_mutex);
597 std::vector<uint8_t> data;
599 j[
"so3_grid_size"] = num;
600 encode(data, j.dump());
602 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
604 std::vector<uint8_t> data_result;
605 std::tie(code, data_result) = readMessage();
607 handleWrongReturnMessage(code, data_result);
613 const std::lock_guard<std::mutex> lock(m_mutex);
614 std::vector<uint8_t> data;
616 send(m_serverSocket,
reinterpret_cast<const char *
>(data.data()),
static_cast<int>(data.size()), 0);
618 std::vector<uint8_t> data_result;
619 std::tie(code, data_result) = readMessage();
621 handleWrongReturnMessage(code, data_result);
623 unsigned int index = 0;
625 decode(data_result, index, jsonStr);
626 json jsonValue = json::parse(jsonStr);
627 std::vector<std::string> result = jsonValue;
634class VISP_EXPORT dummy_vpMegaPose
637 dummy_vpMegaPose() { }
640#if !defined(VISP_BUILD_SHARED_LIBS)
642void 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.
Definition of the vpImage class member functions.
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.
@ GET_LIST_OBJECTS
Ask the server to set the number of samples for coarse estimation.
@ GET_VIZ
Code sent when server returns pose estimates.
@ SET_SO3_GRID_SIZE
Code sent when server returns a pose score.
@ RET_SCORE
Ask the server to score a pose estimate.
@ GET_POSE
Server has successfully completed operation, no return value expected.
@ RET_VIZ
Ask the server for a rendering of the object.
@ OK
An error occurred server side.
@ SET_INTR
Code sent when server returns the rendering of an object.
@ GET_SCORE
Set the intrinsics for the MegaPose server.
@ RET_POSE
Ask the server to estimate poses.
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.