ArMarkerExternalCameraCalibration.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package Imagine::ArmarXObjects::ArMarkerExternalCameraCalibration
17  * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu )
18  * @date 2020
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
24 
25 #include <filesystem>
26 
27 #include <SimoxUtility/json.h>
28 #include <SimoxUtility/math/pose/pose.h>
29 #include <SimoxUtility/math/pose/invert.h>
30 
31 #include <VirtualRobot/XML/RobotIO.h>
32 
36 
37 
38 namespace armarx
39 {
40 
42  {
44 
45  defs->component(localizer);
46  defs->defineOptionalProperty<std::string>("cmp.PointCloudToArViz", "PointCloudToArViz", "Name of the PointCloudToArViz component.");
47 
48  defs->optional(localizerMarkerID, "loc.MarkerID", "The marker ID to use (-1 for any ID).");
49 
50  defs->optional(robotArMarkerFileName, "robot.ArMarkerRobotFileName", "File name of robot model with ArMarker marker.");
51  defs->optional(robotBaseNodeName, "robot.BaseNodeName", "Name of the base robot node.");
52  defs->optional(robotArMarkerMarkerNodeName, "robot.ArMarkerMarkerNodeName", "Name of the ArMarker marker robot node.");
53 
54  defs->optional(calibrationFilePath, "calibrationFilePath", "Path to the calibration file.");
55 
56  return defs;
57  }
58 
60  {
61  return "ArMarkerExternalCameraCalibration";
62  }
63 
64 
66  {
67  namespace fs = std::filesystem;
68 
69  {
70  robotArMarkerFileName = ArmarXDataPath::resolvePath(robotArMarkerFileName);
71  ARMARX_INFO << "Loading robot with ArMarker marker from: " << robotArMarkerFileName;
72  robotArMarker = VirtualRobot::RobotIO::loadRobot(robotArMarkerFileName, VirtualRobot::RobotIO::RobotDescription::eStructure);
73  }
74 
75  {
76  fs::path path = calibrationFilePath;
77  fs::path parent_path = ArmarXDataPath::resolvePath(path.parent_path());
78  this->calibrationFilePath = parent_path / path.filename();
79  ARMARX_INFO << "Calibration file: " << calibrationFilePath;
80  }
81  }
82 
83 
85  {
86  getProxyFromProperty(vis.pointCloudToArViz, "cmp.PointCloudToArViz", false, "", false);
87  if (vis.pointCloudToArViz)
88  {
89  ARMARX_INFO << "Found PointCloudToArViz.";
90  }
91 
94 
95  {
96  vis.layerCamera = arviz.layer("In Camera");
97  vis.layerCamera.add(viz::Pose("Origin"));
98  vis.layerCamera.add(vis.markerPoseInCamera);
99 
100  vis.layerRobotBase = arviz.layer("In RobotBase");
101  vis.layerRobotBase.add(vis.markerPoseInRobotBase);
102  vis.layerRobotBase.add(vis.markerModelInRobotBase);
103  vis.layerRobotBase.add(vis.cameraPoseInRobotBase);
104  }
105 
106 
107 
108  if (task)
109  {
110  task->stop();
111  task->join();
112  task = nullptr;
113  }
114  task = new SimpleRunningTask<>([this]()
115  {
116  this->run();
117  });
118  task->start();
119  }
120 
121 
123  {
124  task->stop();
125  localizer = nullptr;
126  }
127 
128 
130  {
131  }
132 
133  void ArMarkerExternalCameraCalibration::run()
134  {
135  CycleUtil cycle(50);
136  while (!task->isStopped())
137  {
138  if (!localizer)
139  {
140  break; // Localizer disconnected. Wait for reconnect.
141  }
142 
143  visionx::ArMarkerLocalizationResultList localizationResults;
144  try
145  {
146  localizationResults = localizer->GetLatestLocalizationResult();
147  }
148  catch (const Ice::ConnectionRefusedException&)
149  {
150  break; // Localizer disconnected. Wait for reconnect.
151  }
152 
153  ARMARX_VERBOSE << "Got " << localizationResults.size() << " localization results.";
154 
155  std::optional<visionx::ArMarkerLocalizationResult> result;
156  if (localizationResults.size() > 0)
157  {
158  if (localizerMarkerID < 0)
159  {
160  result = localizationResults.front();
161  }
162  else
163  {
164  for (const auto& r : localizationResults)
165  {
166  if (r.id == localizerMarkerID)
167  {
168  result = r;
169  break;
170  }
171  }
172  }
173  }
174 
175  if (result)
176  {
177  ARMARX_VERBOSE << "Using marker with id " << result->id;
178  FramedPosePtr framedPose = FramedPosePtr::dynamicCast(result->pose);
179  Eigen::Matrix4f pose = framedPose->toEigen();
180 
181  onLocalizationResult(pose);
182  }
183  else
184  {
185  vis.markerPoseInCamera.scale(0.5);
186  }
187 
188  arviz.commit({vis.layerCamera, vis.layerRobotBase});
189 
190  cycle.waitForCycleDuration();
191  }
192  }
193 
194  void ArMarkerExternalCameraCalibration::onLocalizationResult(const Eigen::Matrix4f& markerPoseInCamera)
195  {
196  RobotState::synchronizeLocalClone(robotArMarker);
197 
198  Eigen::Matrix4f cameraPoseMarker = simox::math::inverted_pose(markerPoseInCamera);
199 
200  VirtualRobot::RobotNodePtr arMarkerNode = robotArMarker->getRobotNode(robotArMarkerMarkerNodeName);
201  VirtualRobot::RobotNodePtr baseNode = robotArMarker->getRobotNode(robotBaseNodeName);
202 
203  FramedPose framedCameraPose(cameraPoseMarker, arMarkerNode->getName(), robotArMarker->getName());
204  framedCameraPose.changeFrame(robotArMarker, baseNode->getName());
205 
206  Eigen::Matrix4f cameraPoseInRobotBase = framedCameraPose.toEigen();
207  Eigen::Matrix4f markerInRobotBase = cameraPoseInRobotBase * markerPoseInCamera;
208 
209  vis.markerPoseInCamera.pose(markerPoseInCamera).scale(1.0);
210  vis.markerPoseInRobotBase.pose(baseNode->getPoseInRootFrame() * markerInRobotBase);
211  vis.cameraPoseInRobotBase.pose(baseNode->getPoseInRootFrame() * cameraPoseInRobotBase);
212  {
213  FramedPose framedMarkerModelPose(Eigen::Matrix4f::Identity(), arMarkerNode->getName(), robotArMarker->getName());
214  framedMarkerModelPose.changeFrame(robotArMarker, baseNode->getName());
215  vis.markerModelInRobotBase.pose(baseNode->getPoseInRootFrame() * framedMarkerModelPose.toEigen());
216  }
217 
218  {
219  std::scoped_lock lock(markerPoseMutex);
220  this->markerPoseInCamera = markerPoseInCamera;
221  this->cameraPoseInRobotBase = cameraPoseInRobotBase;
222  }
223  if (vis.pointCloudToArViz)
224  {
225  vis.pointCloudToArViz->setCustomTransform(new Pose(baseNode->getPoseInRootFrame() * cameraPoseInRobotBase));
226  }
227  }
228 
229 
230  void ArMarkerExternalCameraCalibration::storeCalibration()
231  {
232  ExternalCameraCalibration calibration;
233  {
234  std::scoped_lock lock(markerPoseMutex);
235  calibration.cameraPose = cameraPoseInRobotBase;
236  calibration.cameraPoseFrame = robotBaseNodeName;
237  calibration.timestamp = TimeUtil::GetTime();
238  }
239 
240  const nlohmann::json j = calibration;
241 
242  ARMARX_IMPORTANT << "Writing calibration to \n" << calibrationFilePath << "\n\n" << j.dump(2);
243  nlohmann::write_json(calibrationFilePath, j, 2);
244  }
245 
246 
247 
249  {
250  using namespace armarx::RemoteGui::Client;
251 
252  tab.storeButton.setLabel("Store calibration");
253 
254  VBoxLayout root { tab.storeButton, VSpacer() };
255  RemoteGui_createTab(getName(), root, &tab);
256  }
257 
259  {
260  if (tab.storeButton.wasClicked())
261  {
262  storeCalibration();
263  }
264  }
265 
266 }
armarx::ArmarXDataPath::resolvePath
static std::string resolvePath(const std::string &path, bool verbose=true)
Resolves environment variables and home paths and tries to make path absolute.
Definition: ArmarXDataPath.cpp:542
armarx::SimpleRunningTask
Usage:
Definition: TaskUtil.h:70
armarx::viz::Client::commit
CommitResult commit(StagedCommit const &commit)
Definition: Client.cpp:80
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
armarx::VariantType::FramedPose
const VariantTypeId FramedPose
Definition: FramedPose.h:37
armarx::RemoteGui::Client::VBoxLayout
Definition: Widgets.h:167
armarx::ArMarkerExternalCameraCalibration::getDefaultName
std::string getDefaultName() const override
Definition: ArMarkerExternalCameraCalibration.cpp:59
armarx::FramedPosePtr
IceInternal::Handle< FramedPose > FramedPosePtr
Definition: FramedPose.h:250
armarx::CycleUtil
This util class helps with keeping a cycle time during a control cycle.
Definition: CycleUtil.h:40
armarx::ArMarkerExternalCameraCalibration::RemoteGui_update
void RemoteGui_update() override
Definition: ArMarkerExternalCameraCalibration.cpp:258
armarx::RemoteGui::Client::VSpacer
Definition: Widgets.h:204
armarx::RobotStateComponentPluginUser::synchronizeLocalClone
bool synchronizeLocalClone(const VirtualRobot::RobotPtr &robot) const
Definition: RobotStateComponentPlugin.cpp:371
armarx::ArMarkerExternalCameraCalibration::onExitComponent
void onExitComponent() override
Definition: ArMarkerExternalCameraCalibration.cpp:129
armarx::Component::getProxyFromProperty
ProxyType getProxyFromProperty(const std::string &propertyName, bool addToDependencies=false, const std::string &endpoints="", bool throwOnProxyError=true)
Get a proxy whose name is specified by the given property.
Definition: Component.h:236
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
armarx::ArMarkerExternalCameraCalibration::createRemoteGuiTab
void createRemoteGuiTab()
Definition: ArMarkerExternalCameraCalibration.cpp:248
FramedPose.h
armarx::ArMarkerExternalCameraCalibration::onConnectComponent
void onConnectComponent() override
Definition: ArMarkerExternalCameraCalibration.cpp:84
armarx::viz::Pose
Definition: Elements.h:179
armarx::ArMarkerExternalCameraCalibration::onInitComponent
void onInitComponent() override
Definition: ArMarkerExternalCameraCalibration.cpp:65
armarx::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_startRunningTask
void RemoteGui_startRunningTask()
Definition: LightweightRemoteGuiComponentPlugin.cpp:110
CycleUtil.h
ExpressionException.h
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
armarx::ArMarkerExternalCameraCalibration::onDisconnectComponent
void onDisconnectComponent() override
Definition: ArMarkerExternalCameraCalibration.cpp:122
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:601
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:70
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::ArVizComponentPluginUser::arviz
armarx::viz::Client arviz
Definition: ArVizComponentPlugin.h:43
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_createTab
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
Definition: LightweightRemoteGuiComponentPlugin.cpp:95
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::ArMarkerExternalCameraCalibration::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: ArMarkerExternalCameraCalibration.cpp:41
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:107
armarx::viz::Client::layer
Layer layer(std::string const &name) const
Definition: Client.cpp:73
ArMarkerExternalCameraCalibration.h
armarx::RemoteGui::Client
Definition: EigenWidgets.cpp:8
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28