Visual Servoing Platform  version 3.1.0
vpXmlParserCamera.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * XML parser to load and save camera intrinsic parameters.
33  *
34  * Authors:
35  * Anthony Saunier
36  *
37  *****************************************************************************/
38 
45 #include <visp3/core/vpXmlParserCamera.h>
46 #ifdef VISP_HAVE_XML2
47 
48 #include <stdlib.h>
49 #include <string.h>
50 
51 #include <visp3/core/vpDebug.h>
52 /* --------------------------------------------------------------------------
53  */
54 /* --- LABEL XML ------------------------------------------------------------
55  */
56 /* --------------------------------------------------------------------------
57  */
58 
59 #define LABEL_XML_ROOT "root"
60 #define LABEL_XML_CAMERA "camera"
61 #define LABEL_XML_CAMERA_NAME "name"
62 #define LABEL_XML_WIDTH "image_width"
63 #define LABEL_XML_HEIGHT "image_height"
64 #define LABEL_XML_SUBSAMPLING_WIDTH "subsampling_width"
65 #define LABEL_XML_SUBSAMPLING_HEIGHT "subsampling_height"
66 #define LABEL_XML_FULL_WIDTH "full_width"
67 #define LABEL_XML_FULL_HEIGHT "full_height"
68 #define LABEL_XML_MODEL "model"
69 #define LABEL_XML_MODEL_TYPE "type"
70 #define LABEL_XML_U0 "u0"
71 #define LABEL_XML_V0 "v0"
72 #define LABEL_XML_PX "px"
73 #define LABEL_XML_PY "py"
74 #define LABEL_XML_KUD "kud"
75 #define LABEL_XML_KDU "kdu"
76 
77 #define LABEL_XML_MODEL_WITHOUT_DISTORTION "perspectiveProjWithoutDistortion"
78 #define LABEL_XML_MODEL_WITH_DISTORTION "perspectiveProjWithDistortion"
79 
80 #define LABEL_XML_ADDITIONAL_INFO "additional_information"
81 
85  : vpXmlParser(), camera(), camera_name(), image_width(0), image_height(0), subsampling_width(0),
86  subsampling_height(0), full_width(0), full_height(0)
87 {
88 }
94  : vpXmlParser(twinParser), camera(twinParser.camera), camera_name(twinParser.camera_name), image_width(0),
95  image_height(0), subsampling_width(0), subsampling_height(0), full_width(0), full_height(0)
96 
97 {
98  this->image_width = twinParser.image_width;
99  this->image_height = twinParser.image_height;
100  this->subsampling_width = twinParser.subsampling_width;
101  this->subsampling_height = twinParser.subsampling_height;
102  this->full_width = twinParser.full_width;
103  this->full_height = twinParser.full_height;
104 }
105 
112 {
113  this->camera = twinParser.camera;
114  this->camera_name = twinParser.camera_name;
115  this->image_width = twinParser.image_width;
116  this->image_height = twinParser.image_height;
117  this->subsampling_width = twinParser.subsampling_width;
118  this->subsampling_height = twinParser.subsampling_height;
119  this->full_width = twinParser.full_width;
120  this->full_height = twinParser.full_height;
121  return *this;
122 }
123 
138 int vpXmlParserCamera::parse(vpCameraParameters &cam, const std::string &filename, const std::string &cam_name,
140  const unsigned int im_width, const unsigned int im_height)
141 {
142  xmlDocPtr doc;
143  xmlNodePtr node;
144 
145  doc = xmlParseFile(filename.c_str());
146  if (doc == NULL) {
147  return SEQUENCE_ERROR;
148  }
149 
150  node = xmlDocGetRootElement(doc);
151  if (node == NULL) {
152  xmlFreeDoc(doc);
153  return SEQUENCE_ERROR;
154  }
155 
156  int ret = this->read(doc, node, cam_name, projModel, im_width, im_height);
157 
158  cam = camera;
159 
160  xmlFreeDoc(doc);
161 
162  return ret;
163 }
164 
208 int vpXmlParserCamera::save(const vpCameraParameters &cam, const std::string &filename, const std::string &cam_name,
209  const unsigned int im_width, const unsigned int im_height,
210  const std::string &additionalInfo)
211 {
212  xmlDocPtr doc;
213  xmlNodePtr node;
214  xmlNodePtr nodeCamera = NULL;
215 
216  doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOWARNING + XML_PARSE_NOERROR + XML_PARSE_NOBLANKS);
217  if (doc == NULL) {
218  doc = xmlNewDoc((xmlChar *)"1.0");
219  node = xmlNewNode(NULL, (xmlChar *)LABEL_XML_ROOT);
220  xmlDocSetRootElement(doc, node);
221  xmlNodePtr node_tmp = xmlNewComment((xmlChar *)"This file stores intrinsic camera parameters used\n"
222  " in the vpCameraParameters Class of ViSP available\n"
223  " at https://visp.inria.fr/download/ .\n"
224  " It can be read with the parse method of\n"
225  " the vpXmlParserCamera class.");
226  xmlAddChild(node, node_tmp);
227  }
228 
229  node = xmlDocGetRootElement(doc);
230  if (node == NULL) {
231  xmlFreeDoc(doc);
232  return SEQUENCE_ERROR;
233  }
234 
235  this->camera = cam;
236 
237  int nbCamera = count(doc, node, cam_name, cam.get_projModel(), im_width, im_height);
238  if (nbCamera > 0) {
239  // vpCERROR << nbCamera
240  // << " set(s) of camera parameters is(are) already "<<
241  // std::endl
242  // << "available in the file with your specifications : "<<
243  // std::endl
244  // << "precise the grabber parameters or delete manually"<<
245  // std::endl
246  // << "the previous one."<<std::endl;
247  xmlFreeDoc(doc);
248  return SEQUENCE_ERROR;
249  }
250 
251  nodeCamera = find_camera(doc, node, cam_name, im_width, im_height);
252  if (nodeCamera == NULL) {
253  write(node, cam_name, im_width, im_height);
254  } else {
255  write_camera(nodeCamera);
256  }
257 
258  if (!additionalInfo.empty()) {
259  // Get camera node pointer
260  nodeCamera = find_camera(doc, node, cam_name, im_width, im_height);
261 
262  // Additional information provided by the user
263  xmlNodePtr nodeAdditionalInfo = find_additional_info(nodeCamera);
264 
265  if (nodeAdditionalInfo == NULL) {
266  // Create the additional information node
267  xmlNodePtr node_comment = xmlNewComment((xmlChar *)"Additional information");
268  xmlAddChild(nodeCamera, node_comment);
269 
270  nodeAdditionalInfo = xmlNewNode(NULL, (xmlChar *)LABEL_XML_ADDITIONAL_INFO);
271  xmlAddChild(nodeCamera, nodeAdditionalInfo);
272  }
273 
274  if (nodeAdditionalInfo != NULL) {
275  // Add the information in this specific node
276  xmlNodePtr pNewNode = NULL;
277  xmlParseInNodeContext(nodeAdditionalInfo, additionalInfo.c_str(), (int)additionalInfo.length(), 0, &pNewNode);
278  if (pNewNode != NULL) {
279  while (pNewNode != NULL) {
280  xmlAddChild(nodeAdditionalInfo, xmlCopyNode(pNewNode, 1));
281  pNewNode = pNewNode->next;
282  }
283 
284  xmlFreeNode(pNewNode);
285  }
286  }
287  }
288 
289  xmlSaveFormatFile(filename.c_str(), doc, 1);
290  xmlFreeDoc(doc);
291 
292  return SEQUENCE_OK;
293 }
294 
313 int vpXmlParserCamera::read(xmlDocPtr doc, xmlNodePtr node, const std::string &cam_name,
315  const unsigned int im_width, const unsigned int im_height,
316  const unsigned int subsampl_width, const unsigned int subsampl_height)
317 {
318  // char * val_char;
319  vpXmlCodeType prop;
320 
322  unsigned int nbCamera = 0;
323 
324  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
325  if (node->type != XML_ELEMENT_NODE)
326  continue;
327  if (SEQUENCE_OK != str2xmlcode((char *)(node->name), prop)) {
328  prop = CODE_XML_OTHER;
329  back = SEQUENCE_ERROR;
330  }
331  /*
332  switch (prop)
333  {
334  case CODE_XML_CAMERA:
335  if (SEQUENCE_OK == this->read_camera (doc, node, camera_name, projModel,
336  image_width, image_height, subsampling_width, subsampling_height)){
337  nbCamera++;
338  }
339  break;
340  default:
341  back = SEQUENCE_ERROR;
342  break;
343  }
344  */
345  if (prop == CODE_XML_CAMERA) {
346  if (SEQUENCE_OK ==
347  this->read_camera(doc, node, cam_name, projModel, im_width, im_height, subsampl_width, subsampl_height))
348  nbCamera++;
349  } else
350  back = SEQUENCE_ERROR;
351  }
352 
353  if (nbCamera == 0) {
354  back = SEQUENCE_ERROR;
355  vpCERROR << "No camera parameters is available" << std::endl << "with your specifications" << std::endl;
356  } else if (nbCamera > 1) {
357  back = SEQUENCE_ERROR;
358  vpCERROR << nbCamera << " sets of camera parameters are available" << std::endl
359  << "with your specifications : " << std::endl
360  << "precise your choice..." << std::endl;
361  }
362 
363  return back;
364 }
384 int vpXmlParserCamera::count(xmlDocPtr doc, xmlNodePtr node, const std::string &cam_name,
386  const unsigned int im_width, const unsigned int im_height,
387  const unsigned int subsampl_width, const unsigned int subsampl_height)
388 {
389  // char * val_char;
390  vpXmlCodeType prop;
391  int nbCamera = 0;
392 
393  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
394  if (node->type != XML_ELEMENT_NODE)
395  continue;
396  if (SEQUENCE_OK != str2xmlcode((char *)(node->name), prop)) {
397  prop = CODE_XML_OTHER;
398  }
399  /*
400  switch (prop)
401  {
402  case CODE_XML_CAMERA:
403  if (SEQUENCE_OK == this->read_camera (doc, node, camera_name, projModel,
404  image_width, image_height,
405  subsampling_width, subsampling_height)){
406  nbCamera++;
407  }
408  break;
409  default:
410  break;
411  }
412  */
413  if (prop == CODE_XML_CAMERA) {
414  if (SEQUENCE_OK ==
415  this->read_camera(doc, node, cam_name, projModel, im_width, im_height, subsampl_width, subsampl_height))
416  nbCamera++;
417  }
418  }
419 
420  return nbCamera;
421 }
422 
442 xmlNodePtr vpXmlParserCamera::find_camera(xmlDocPtr doc, xmlNodePtr node, const std::string &cam_name,
443  const unsigned int im_width, const unsigned int im_height,
444  const unsigned int subsampl_width, const unsigned int subsampl_height)
445 {
446  // char * val_char;
447  vpXmlCodeType prop;
448 
449  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
450  if (node->type != XML_ELEMENT_NODE)
451  continue;
452  if (SEQUENCE_OK != str2xmlcode((char *)(node->name), prop)) {
453  prop = CODE_XML_OTHER;
454  }
455  /*
456  switch (prop)
457  {
458  case CODE_XML_CAMERA:
459  if (SEQUENCE_OK == this->read_camera_header(doc, node, camera_name,
460  image_width, image_height,
461  subsampling_width, subsampling_height)){
462  return node;
463  }
464  break;
465  default:
466  break;
467  }
468  */
469  if (prop == CODE_XML_CAMERA) {
470  if (SEQUENCE_OK ==
471  this->read_camera_header(doc, node, cam_name, im_width, im_height, subsampl_width, subsampl_height))
472  return node;
473  }
474  }
475  return NULL;
476 }
477 
487 xmlNodePtr vpXmlParserCamera::find_additional_info(xmlNodePtr node)
488 {
489  vpXmlCodeType prop;
490 
491  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
492  if (node->type != XML_ELEMENT_NODE) {
493  continue;
494  }
495 
496  if (SEQUENCE_OK != str2xmlcode((char *)(node->name), prop)) {
497  prop = CODE_XML_OTHER;
498  }
499 
500  if (prop == CODE_XML_ADDITIONAL_INFO) {
501  // We found the node
502  return node;
503  }
504  }
505 
506  return NULL;
507 }
508 
528 int vpXmlParserCamera::read_camera(xmlDocPtr doc, xmlNodePtr node, const std::string &cam_name,
530  const unsigned int im_width, const unsigned int im_height,
531  const unsigned int subsampl_width, const unsigned int subsampl_height)
532 {
533  vpXmlCodeType prop;
534  /* read value in the XML file. */
535  std::string camera_name_tmp = "";
536  unsigned int image_height_tmp = 0;
537  unsigned int image_width_tmp = 0;
538  unsigned int subsampling_width_tmp = 0;
539  unsigned int subsampling_height_tmp = 0;
540  // unsigned int full_width_tmp = 0;
541  // unsigned int full_height_tmp = 0;
542  vpCameraParameters cam_tmp;
543  vpCameraParameters cam_tmp_model;
544  bool projModelFound = false;
546 
547  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
548  // vpDEBUG_TRACE (15, "Carac : %s.", node ->name);
549  if (node->type != XML_ELEMENT_NODE)
550  continue;
551  if (SEQUENCE_OK != str2xmlcode((char *)(node->name), prop)) {
552  prop = CODE_XML_OTHER;
553  back = SEQUENCE_ERROR;
554  }
555 
556  switch (prop) {
557  case CODE_XML_CAMERA_NAME: {
558  char *val_char = xmlReadCharChild(doc, node);
559  camera_name_tmp = val_char;
560  std::cout << "Found camera with name: \"" << camera_name_tmp << "\"" << std::endl;
561  xmlFree(val_char);
562  break;
563  }
564  case CODE_XML_WIDTH:
565  image_width_tmp = xmlReadUnsignedIntChild(doc, node);
566  break;
567 
568  case CODE_XML_HEIGHT:
569  image_height_tmp = xmlReadUnsignedIntChild(doc, node);
570  break;
572  subsampling_width_tmp = xmlReadUnsignedIntChild(doc, node);
573  break;
575  subsampling_height_tmp = xmlReadUnsignedIntChild(doc, node);
576  break;
577  // case CODE_XML_FULL_WIDTH:
578  // full_width_tmp = xmlReadUnsignedIntChild(doc, node);
579  // break;
580 
581  // case CODE_XML_FULL_HEIGHT:
582  // full_height_tmp = xmlReadUnsignedIntChild(doc, node);
583  // break;
584 
585  case CODE_XML_MODEL:
586  back = read_camera_model(doc, node, cam_tmp_model);
587  if (cam_tmp_model.get_projModel() == projModel) {
588  cam_tmp = cam_tmp_model;
589  projModelFound = true;
590  }
591  break;
592 
594  break;
595 
596  case CODE_XML_BAD:
597  case CODE_XML_OTHER:
598  case CODE_XML_CAMERA:
600  case CODE_XML_FULL_WIDTH:
601  case CODE_XML_MODEL_TYPE:
602  case CODE_XML_U0:
603  case CODE_XML_V0:
604  case CODE_XML_PX:
605  case CODE_XML_PY:
606  case CODE_XML_KUD:
607  case CODE_XML_KDU:
608  default:
609  back = SEQUENCE_ERROR;
610  break;
611  }
612  }
613  // Create a specific test for subsampling_width and subsampling_height to
614  // ensure that division by zero is not possible in the next test
615  bool test_subsampling_width = true;
616  bool test_subsampling_height = true;
617 
618  if (subsampling_width) {
619  test_subsampling_width = (abs((int)subsampl_width - (int)subsampling_width_tmp) <
620  (allowedPixelDiffOnImageSize * (int)(subsampling_width_tmp / subsampling_width)));
621  }
622  if (subsampling_height) {
623  test_subsampling_height = (abs((int)subsampl_height - (int)subsampling_height_tmp) <
624  (allowedPixelDiffOnImageSize * (int)(subsampling_height_tmp / subsampling_height)));
625  }
626  if (!((projModelFound == true) && (cam_name == camera_name_tmp) &&
627  (abs((int)im_width - (int)image_width_tmp) < allowedPixelDiffOnImageSize || im_width == 0) &&
628  (abs((int)im_height - (int)image_height_tmp) < allowedPixelDiffOnImageSize || im_height == 0) &&
629  (test_subsampling_width) && (test_subsampling_height))) {
630  back = SEQUENCE_ERROR;
631  } else {
632  this->camera = cam_tmp;
633  this->camera_name = camera_name_tmp;
634  this->image_width = image_width_tmp;
635  this->image_height = image_height_tmp;
636  this->subsampling_width = subsampling_width_tmp;
637  this->subsampling_height = subsampling_height_tmp;
638  this->full_width = subsampling_width_tmp * image_width_tmp;
639  this->full_height = subsampling_height_tmp * image_height_tmp;
640  }
641  return back;
642 }
662 int vpXmlParserCamera::read_camera_header(xmlDocPtr doc, xmlNodePtr node, const std::string &cam_name,
663  const unsigned int im_width, const unsigned int im_height,
664  const unsigned int subsampl_width, const unsigned int subsampl_height)
665 {
666  vpXmlCodeType prop;
667  /* read value in the XML file. */
668  std::string camera_name_tmp = "";
669  unsigned int image_height_tmp = 0;
670  unsigned int image_width_tmp = 0;
671  unsigned int subsampling_width_tmp = 0;
672  unsigned int subsampling_height_tmp = 0;
673  // unsigned int full_width_tmp = 0;
674  // unsigned int full_height_tmp = 0;
676 
677  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
678  // vpDEBUG_TRACE (15, "Carac : %s.", node ->name);
679  if (node->type != XML_ELEMENT_NODE)
680  continue;
681  if (SEQUENCE_OK != str2xmlcode((char *)(node->name), prop)) {
682  prop = CODE_XML_OTHER;
683  back = SEQUENCE_ERROR;
684  }
685 
686  switch (prop) {
687  case CODE_XML_CAMERA_NAME: {
688  char *val_char = xmlReadCharChild(doc, node);
689  camera_name_tmp = val_char;
690  xmlFree(val_char);
691  } break;
692 
693  case CODE_XML_WIDTH:
694  image_width_tmp = xmlReadUnsignedIntChild(doc, node);
695  break;
696 
697  case CODE_XML_HEIGHT:
698  image_height_tmp = xmlReadUnsignedIntChild(doc, node);
699  break;
701  subsampling_width_tmp = xmlReadUnsignedIntChild(doc, node);
702  break;
704  subsampling_height_tmp = xmlReadUnsignedIntChild(doc, node);
705  break;
706  // case CODE_XML_FULL_WIDTH:
707  // full_width_tmp = xmlReadUnsignedIntChild(doc, node);
708  // break;
709 
710  // case CODE_XML_FULL_HEIGHT:
711  // full_height_tmp = xmlReadUnsignedIntChild(doc, node);
712  // break;
713 
714  case CODE_XML_MODEL:
715  break;
716 
718  break;
719 
720  case CODE_XML_BAD:
721  case CODE_XML_OTHER:
722  case CODE_XML_CAMERA:
724  case CODE_XML_FULL_WIDTH:
725  case CODE_XML_MODEL_TYPE:
726  case CODE_XML_U0:
727  case CODE_XML_V0:
728  case CODE_XML_PX:
729  case CODE_XML_PY:
730  case CODE_XML_KUD:
731  case CODE_XML_KDU:
732  default:
733  back = SEQUENCE_ERROR;
734  break;
735  }
736  }
737  if (!((cam_name == camera_name_tmp) && (im_width == image_width_tmp || im_width == 0) &&
738  (im_height == image_height_tmp || im_height == 0) &&
739  (subsampl_width == subsampling_width_tmp || subsampl_width == 0) &&
740  (subsampl_height == subsampling_height_tmp || subsampl_height == 0))) {
741  back = SEQUENCE_ERROR;
742  }
743  return back;
744 }
745 
756 vpXmlParserCamera::vpXmlCodeSequenceType vpXmlParserCamera::read_camera_model(xmlDocPtr doc, xmlNodePtr node,
757  vpCameraParameters &cam_tmp)
758 {
759  // counter of the number of read parameters
760  int nb = 0;
761  vpXmlCodeType prop;
762  /* read value in the XML file. */
763 
764  char *model_type = NULL;
765  double u0 = cam_tmp.get_u0();
766  double v0 = cam_tmp.get_v0();
767  double px = cam_tmp.get_px();
768  double py = cam_tmp.get_py();
769  double kud = cam_tmp.get_kud();
770  double kdu = cam_tmp.get_kdu();
772  int validation = 0;
773 
774  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
775  // vpDEBUG_TRACE (15, "Carac : %s.", node ->name);
776  if (node->type != XML_ELEMENT_NODE)
777  continue;
778  if (SEQUENCE_OK != str2xmlcode((char *)(node->name), prop)) {
779  prop = CODE_XML_OTHER;
780  back = SEQUENCE_ERROR;
781  }
782 
783  switch (prop) {
784  case CODE_XML_MODEL_TYPE: {
785  if (model_type != NULL) {
786  xmlFree(model_type);
787  }
788  model_type = xmlReadCharChild(doc, node);
789  nb++;
790  validation = validation | 0x01;
791  } break;
792  case CODE_XML_U0:
793  u0 = xmlReadDoubleChild(doc, node);
794  nb++;
795  validation = validation | 0x02;
796  break;
797  case CODE_XML_V0:
798  v0 = xmlReadDoubleChild(doc, node);
799  nb++;
800  validation = validation | 0x04;
801  break;
802  case CODE_XML_PX:
803  px = xmlReadDoubleChild(doc, node);
804  nb++;
805  validation = validation | 0x08;
806  break;
807  case CODE_XML_PY:
808  py = xmlReadDoubleChild(doc, node);
809  nb++;
810  validation = validation | 0x10;
811  break;
812  case CODE_XML_KUD:
813  kud = xmlReadDoubleChild(doc, node);
814  nb++;
815  validation = validation | 0x20;
816  break;
817  case CODE_XML_KDU:
818  kdu = xmlReadDoubleChild(doc, node);
819  nb++;
820  validation = validation | 0x40;
821  break;
822  case CODE_XML_BAD:
823  case CODE_XML_OTHER:
824  case CODE_XML_CAMERA:
826  case CODE_XML_HEIGHT:
827  case CODE_XML_WIDTH:
831  case CODE_XML_FULL_WIDTH:
832  case CODE_XML_MODEL:
834  default:
835  back = SEQUENCE_ERROR;
836  break;
837  }
838  }
839 
840  if (model_type == NULL) {
841  vpERROR_TRACE("projection model type doesn't match with any known model !");
842  return SEQUENCE_ERROR;
843  }
844 
845  if (!strcmp(model_type, LABEL_XML_MODEL_WITHOUT_DISTORTION)) {
846  if (nb != 5 || validation != 0x1F) {
847  vpCERROR << "ERROR in 'model' field:\n";
848  vpCERROR << "it must contain 5 parameters\n";
849  xmlFree(model_type);
850 
851  return SEQUENCE_ERROR;
852  }
853  cam_tmp.initPersProjWithoutDistortion(px, py, u0, v0);
854  } else if (!strcmp(model_type, LABEL_XML_MODEL_WITH_DISTORTION)) {
855  if (nb != 7 || validation != 0x7F) {
856  vpCERROR << "ERROR in 'model' field:\n";
857  vpCERROR << "it must contain 7 parameters\n";
858  xmlFree(model_type);
859 
860  return SEQUENCE_ERROR;
861  }
862  cam_tmp.initPersProjWithDistortion(px, py, u0, v0, kud, kdu);
863  } else {
864  vpERROR_TRACE("projection model type doesn't match with any known model !");
865  xmlFree(model_type);
866 
867  return SEQUENCE_ERROR;
868  }
869  xmlFree(model_type);
870 
871  return back;
872 }
873 
891 int vpXmlParserCamera::write(xmlNodePtr node, const std::string &cam_name, const unsigned int im_width,
892  const unsigned int im_height, const unsigned int subsampl_width,
893  const unsigned int subsampl_height)
894 {
895  int back = SEQUENCE_OK;
896 
897  xmlNodePtr node_tmp;
898  xmlNodePtr node_camera;
899 
900  // <camera>
901  node_camera = xmlNewNode(NULL, (xmlChar *)LABEL_XML_CAMERA);
902  xmlAddChild(node, node_camera);
903  {
904  //<name>
905 
906  if (!cam_name.empty()) {
907  node_tmp = xmlNewComment((xmlChar *)"Name of the camera");
908  xmlAddChild(node_camera, node_tmp);
909  xmlNewTextChild(node_camera, NULL, (xmlChar *)LABEL_XML_CAMERA_NAME, (xmlChar *)cam_name.c_str());
910  }
911 
912  if (im_width != 0 || im_height != 0) {
913  char str[11];
914  //<image_width>
915  node_tmp = xmlNewComment((xmlChar *)"Size of the image on which camera "
916  "calibration was performed");
917  xmlAddChild(node_camera, node_tmp);
918 
919  sprintf(str, "%u", im_width);
920  xmlNewTextChild(node_camera, NULL, (xmlChar *)LABEL_XML_WIDTH, (xmlChar *)str);
921  //<image_height>
922 
923  sprintf(str, "%u", im_height);
924  xmlNewTextChild(node_camera, NULL, (xmlChar *)LABEL_XML_HEIGHT, (xmlChar *)str);
925  if (subsampling_width != 0 || subsampling_height != 0) {
926  node_tmp = xmlNewComment((xmlChar *)"Subsampling used to obtain the "
927  "current size of the image.");
928  xmlAddChild(node_camera, node_tmp);
929 
930  //<subsampling_width>
931  sprintf(str, "%u", subsampl_width);
932  xmlNewTextChild(node_camera, NULL, (xmlChar *)LABEL_XML_SUBSAMPLING_WIDTH, (xmlChar *)str);
933  //<subsampling_height>
934  sprintf(str, "%u", subsampl_height);
935  xmlNewTextChild(node_camera, NULL, (xmlChar *)LABEL_XML_SUBSAMPLING_HEIGHT, (xmlChar *)str);
936  node_tmp = xmlNewComment((xmlChar *)"The full size is the sensor size actually used to "
937  "grab the image. full_width = subsampling_width * "
938  "image_width");
939  xmlAddChild(node_camera, node_tmp);
940 
941  //<full_width>
942  sprintf(str, "%u", im_width * subsampl_width);
943  xmlNewTextChild(node_camera, NULL, (xmlChar *)LABEL_XML_FULL_WIDTH, (xmlChar *)str);
944  //<full_height>
945  sprintf(str, "%u", im_height * subsampl_height);
946  xmlNewTextChild(node_camera, NULL, (xmlChar *)LABEL_XML_FULL_HEIGHT, (xmlChar *)str);
947  }
948  }
949 
950  node_tmp = xmlNewComment((xmlChar *)"Intrinsic camera parameters "
951  "computed for each projection model");
952 
953  xmlAddChild(node_camera, node_tmp);
954 
955  back = write_camera(node_camera);
956  }
957  return back;
958 }
966 int vpXmlParserCamera::write_camera(xmlNodePtr node_camera)
967 {
968  xmlNodePtr node_model;
969  xmlNodePtr node_tmp;
970 
971  int back = SEQUENCE_OK;
972  switch (camera.get_projModel()) {
974  //<model>
975  node_model = xmlNewNode(NULL, (xmlChar *)LABEL_XML_MODEL);
976  xmlAddChild(node_camera, node_model);
977  {
978  char str[21];
979  node_tmp = xmlNewComment((xmlChar *)"Projection model type");
980  xmlAddChild(node_model, node_tmp);
981 
982  //<type>without_distortion</type>
983  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_MODEL_TYPE, (xmlChar *)LABEL_XML_MODEL_WITHOUT_DISTORTION);
984 
985  node_tmp = xmlNewComment((xmlChar *)"Pixel ratio");
986  xmlAddChild(node_model, node_tmp);
987  //<px>
988  sprintf(str, "%.10f", camera.get_px());
989  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_PX, (xmlChar *)str);
990  //<py>
991  sprintf(str, "%.10f", camera.get_py());
992  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_PY, (xmlChar *)str);
993 
994  node_tmp = xmlNewComment((xmlChar *)"Principal point");
995  xmlAddChild(node_model, node_tmp);
996 
997  //<u0>
998  sprintf(str, "%.10f", camera.get_u0());
999  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_U0, (xmlChar *)str);
1000  //<v0>
1001  sprintf(str, "%.10f", camera.get_v0());
1002  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_V0, (xmlChar *)str);
1003  }
1004  break;
1006  //<model>
1007  node_model = xmlNewNode(NULL, (xmlChar *)LABEL_XML_MODEL);
1008  xmlAddChild(node_camera, node_model);
1009  {
1010  char str[21];
1011  node_tmp = xmlNewComment((xmlChar *)"Projection model type");
1012  xmlAddChild(node_model, node_tmp);
1013  //<type>with_distortion</type>
1014  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_MODEL_TYPE, (xmlChar *)LABEL_XML_MODEL_WITH_DISTORTION);
1015 
1016  node_tmp = xmlNewComment((xmlChar *)"Pixel ratio");
1017  xmlAddChild(node_model, node_tmp);
1018  //<px>
1019  sprintf(str, "%.10f", camera.get_px());
1020  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_PX, (xmlChar *)str);
1021  //<py>
1022  sprintf(str, "%.10f", camera.get_py());
1023  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_PY, (xmlChar *)str);
1024 
1025  node_tmp = xmlNewComment((xmlChar *)"Principal point");
1026  xmlAddChild(node_model, node_tmp);
1027  //<u0>
1028  sprintf(str, "%.10f", camera.get_u0());
1029  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_U0, (xmlChar *)str);
1030  //<v0>
1031  sprintf(str, "%.10f", camera.get_v0());
1032  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_V0, (xmlChar *)str);
1033 
1034  //<kud>
1035  node_tmp = xmlNewComment((xmlChar *)"Undistorted to distorted distortion parameter");
1036  xmlAddChild(node_model, node_tmp);
1037  sprintf(str, "%.10f", camera.get_kud());
1038  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_KUD, (xmlChar *)str);
1039 
1040  //<kud>
1041  node_tmp = xmlNewComment((xmlChar *)"Distorted to undistorted distortion parameter");
1042  xmlAddChild(node_model, node_tmp);
1043  sprintf(str, "%.10f", camera.get_kdu());
1044  xmlNewTextChild(node_model, NULL, (xmlChar *)LABEL_XML_KDU, (xmlChar *)str);
1045  }
1046  break;
1047  }
1048  return back;
1049 }
1050 
1059 vpXmlParserCamera::vpXmlCodeSequenceType vpXmlParserCamera::str2xmlcode(char *str, vpXmlCodeType &res)
1060 {
1061  vpXmlCodeType val_int = CODE_XML_BAD;
1063 
1064  // DEBUG_TRACE (9, "# Entree :str=%s.", str);
1065 
1066  if (!strcmp(str, LABEL_XML_CAMERA)) {
1067  val_int = CODE_XML_CAMERA;
1068  } else if (!strcmp(str, LABEL_XML_CAMERA_NAME)) {
1069  val_int = CODE_XML_CAMERA_NAME;
1070  } else if (!strcmp(str, LABEL_XML_MODEL)) {
1071  val_int = CODE_XML_MODEL;
1072  } else if (!strcmp(str, LABEL_XML_MODEL_TYPE)) {
1073  val_int = CODE_XML_MODEL_TYPE;
1074  } else if (!strcmp(str, LABEL_XML_WIDTH)) {
1075  val_int = CODE_XML_WIDTH;
1076  } else if (!strcmp(str, LABEL_XML_HEIGHT)) {
1077  val_int = CODE_XML_HEIGHT;
1078  } else if (!strcmp(str, LABEL_XML_SUBSAMPLING_WIDTH)) {
1079  val_int = CODE_XML_SUBSAMPLING_WIDTH;
1080  } else if (!strcmp(str, LABEL_XML_SUBSAMPLING_HEIGHT)) {
1081  val_int = CODE_XML_SUBSAMPLING_HEIGHT;
1082  } else if (!strcmp(str, LABEL_XML_FULL_WIDTH)) {
1083  val_int = CODE_XML_FULL_WIDTH;
1084  } else if (!strcmp(str, LABEL_XML_FULL_HEIGHT)) {
1085  val_int = CODE_XML_FULL_HEIGHT;
1086  } else if (!strcmp(str, LABEL_XML_U0)) {
1087  val_int = CODE_XML_U0;
1088  } else if (!strcmp(str, LABEL_XML_V0)) {
1089  val_int = CODE_XML_V0;
1090  } else if (!strcmp(str, LABEL_XML_PX)) {
1091  val_int = CODE_XML_PX;
1092  } else if (!strcmp(str, LABEL_XML_PY)) {
1093  val_int = CODE_XML_PY;
1094  } else if (!strcmp(str, LABEL_XML_KUD)) {
1095  val_int = CODE_XML_KUD;
1096  } else if (!strcmp(str, LABEL_XML_KDU)) {
1097  val_int = CODE_XML_KDU;
1098  } else if (!strcmp(str, LABEL_XML_ADDITIONAL_INFO)) {
1099  val_int = CODE_XML_ADDITIONAL_INFO;
1100  } else {
1101  val_int = CODE_XML_OTHER;
1102  }
1103  res = val_int;
1104 
1105  return back;
1106 }
1107 #elif !defined(VISP_BUILD_SHARED_LIBS)
1108 // Work arround to avoid warning: libvisp_core.a(vpXmlParserCamera.cpp.o) has
1109 // no symbols
1110 void dummy_vpXmlParserCamera(){};
1111 #endif // VISP_HAVE_XML2
double get_kdu() const
vpCameraParametersProjType get_projModel() const
vpXmlParserCamera & operator=(const vpXmlParserCamera &twinparser)
#define vpCERROR
Definition: vpDebug.h:365
#define vpERROR_TRACE
Definition: vpDebug.h:393
double xmlReadDoubleChild(xmlDocPtr doc, xmlNodePtr node)
XML parser to load and save intrinsic camera parameters.
char * xmlReadCharChild(xmlDocPtr doc, xmlNodePtr node)
void initPersProjWithoutDistortion(const double px, const double py, const double u0, const double v0)
This class intends to simplify the creation of xml parser based on the libxml2 third party library...
Definition: vpXmlParser.h:177
Generic class defining intrinsic camera parameters.
unsigned int xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
double get_kud() const
int save(const vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const unsigned int image_width=0, const unsigned int image_height=0, const std::string &additionalInfo="")
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, const unsigned int image_width=0, const unsigned int image_height=0)
void initPersProjWithDistortion(const double px, const double py, const double u0, const double v0, const double kud, const double kdu)