cgv
Loading...
Searching...
No Matches
vr_calib.cxx
1#include "vr_calib.h"
2#include <vr/vr_driver.h>
3#include <cgv/utils/file.h>
4#include <sstream>
5#include <fstream>
7#include <cgv/math/pose.h>
8
9namespace cgv {
10 namespace gui {
12 {
13 static vr_calibration singleton;
14 return singleton;
15 }
17 {
18 for (auto dp : vr::get_vr_drivers()) {
19 if (!dp->is_calibration_transformation_enabled())
20 continue;
21 calibration_info[dp->get_driver_name()] = dp->get_tracking_reference_states();
22 float trans[12];
23 dp->put_calibration_transformation(trans);
24 std::cout << dp->get_driver_name() << ":";
25 for (int i = 0; i < 12; ++i)
26 std::cout << " " << trans[i];
27 std::cout << std::endl;
28 }
29 }
31 bool vr_calibration::update_driver_calibration(vr::vr_driver* dp, const std::map<std::string, vr::vr_trackable_state>& target_reference_states) const
32 {
33
34 std::vector<cgv::math::quaternion<float> > relative_rotations;
35 std::vector<cgv::math::fvec<float, 3> > relative_translations;
36
37 if (dp->get_tracking_reference_states().empty()) {
38 std::vector<void*> handles = dp->scan_vr_kits();
39 if (!handles.empty()) {
40 vr::vr_kit_state state;
41 vr::get_vr_kit(handles.front())->query_state(state, 2);
42 }
43 }
44 const auto& refs = dp->get_tracking_reference_states();
45
46 float current_transform_array[12];
47 auto& current_transform = reinterpret_cast<cgv::math::fmat<float, 3, 4>&>(current_transform_array[0]);
48 dp->put_calibration_transformation(current_transform_array);
49
50 std::cout << "update " << dp->get_driver_name() << std::endl;
51 std::cout << "current :";
52 for (int i = 0; i < 12; ++i)
53 std::cout << " " << current_transform_array[i];
54 std::cout << std::endl;
55
56 // iterate target states and generate a relative transformation for each matched serial
57 for (const auto& target : target_reference_states) {
58 // ensure that serial is registered in driver
59 auto iter = refs.find(target.first);
60 if (iter == refs.end())
61 continue;
62 // ensure that base station is tracked
63 if (iter->second.status != vr::VRS_TRACKED)
64 continue;
65 // compute calibration rotation and translation necessary to achieve target pose
66 const auto& target_pose = reinterpret_cast<const cgv::math::fmat<float, 3, 4>&>(target.second.pose[0]);
67 const auto& pose = reinterpret_cast<const cgv::math::fmat<float, 3, 4>&>(iter->second.pose[0]);
68 cgv::math::fmat<float, 3, 4> relative_transformation = target_pose;
69 pose_append(relative_transformation, pose_inverse(pose));
70 relative_rotations.push_back(cgv::math::quaternion<float>(pose_orientation(relative_transformation)));
71 relative_translations.push_back(pose_position(relative_transformation));
72 }
73 // compute average over all transformations
74 cgv::math::quaternion<float> avg_rel_rot(0.0f, 0.0f, 0.0f, 0.0f);
75 cgv::math::fvec<float, 3> avg_rel_tra(0.0f);
76 for (const auto& rr : relative_rotations)
77 avg_rel_rot += rr;
78 avg_rel_rot.normalize();
79 for (const auto& rt : relative_translations)
80 avg_rel_tra += rt;
81 avg_rel_tra *= 1.0f / float(relative_translations.size());
82 // validate consistency
83 bool consistent = true;
84 for (unsigned i = 0; i < relative_rotations.size(); ++i) {
85 if (length(reinterpret_cast<const cgv::math::fvec<float,4>&>(relative_rotations[i]) - avg_rel_rot) > 0.01f) {
86 consistent = false;
87 break;
88 }
89 if (length(relative_translations[i] - avg_rel_tra) > 0.02f) {
90 consistent = false;
91 break;
92 }
93 }
94 if (consistent) {
95 cgv::math::fmat<float, 3, 4> relative_transformation = pose_construct(avg_rel_rot, avg_rel_tra);
96 pose_transform(relative_transformation, current_transform);
98 set_driver_calibration_matrix(dp, current_transform_array);
99 std::cout << "relative :" << relative_transformation << std::endl;
100 std::cout << "new :";
101 for (int i = 0; i < 12; ++i)
102 std::cout << " " << current_transform_array[i];
103 std::cout << std::endl;
104 return true;
105 }
106 return false;
107 }
110 {
111 auto iter = calibration_info.find(dp->get_driver_name());
112 // ensure that new calibration has been read for this driver
113 if (iter == calibration_info.end())
114 return false;
115 return update_driver_calibration(dp, iter->second);
116 }
120 bool vr_calibration::read_calibration(const std::string& file_path, bool update_drivers)
121 {
122 // read calibration file
123 std::string content;
124 if (!cgv::utils::file::read(file_path, content, true))
125 return false;
126 // extract calibration information into temporary map
127 std::map<std::string, std::map<std::string, vr::vr_trackable_state> > read_calibration_info;
128 std::vector<cgv::utils::line> lines;
129 cgv::utils::split_to_lines(content, lines);
130 std::string driver_name;
131 for (auto l : lines) {
132 if (l.size() < 2)
133 continue;
134 if (l[1] != ' ')
135 continue;
136 switch (l[0]) {
137 case 'd' :
138 driver_name = std::string(l.begin + 3, l.size() - 4);
139 break;
140 case 'b' :
141 {
144 std::stringstream ss(std::string(l.begin + 2, l.size() - 2));
145 ss >> orientation >> position;
146 char rest_of_line[500];
147 ss.getline(&rest_of_line[0], 500);
148 std::string serial = std::string(rest_of_line+1);
149 if (!serial.empty()) {
150 if (serial[0] == '"')
151 serial = serial.substr(1, serial.size() - 2);
152 if (!serial.empty()) {
153 auto& pose = reinterpret_cast<cgv::math::fmat<float,3,4>&>(read_calibration_info[driver_name][serial].pose[0]);
154 orientation.normalize();
155 orientation.put_matrix(pose_orientation(pose));
156 pose_position(pose) = position;
157 }
158 }
159 }
160 }
161 }
162 // copy read information over to calibration information
163 for (const auto& driver_info : read_calibration_info)
164 calibration_info[driver_info.first] = driver_info.second;
165
166 // finally iterate drivers and update driver calibrations
167 if (update_drivers) {
168 for (auto dp : vr::get_vr_drivers()) {
169 auto iter = read_calibration_info.find(dp->get_driver_name());
170 // ensure that new calibration has been read for this driver
171 if (iter == read_calibration_info.end())
172 continue;
173 //
174 update_driver_calibration(dp, iter->second);
175 }
176 }
177 return true;
178 }
179 bool vr_calibration::write_calibration(const std::string& file_path) const
180 {
181 std::ofstream os(file_path);
182 if (os.fail())
183 return false;
184 for (const auto& di : calibration_info) {
185 os << "d \"" << di.first << "\"\n";
186 for (const auto& s : di.second) {
187 os << "b ";
188 const auto& pose = reinterpret_cast<const cgv::math::fmat<float, 3, 4>&>(s.second.pose[0]);
189 cgv::math::quaternion<float> orientation(pose_orientation(pose));
190 os << orientation << " " << pose_position(pose) << " \"" << s.first << "\"\n";
191 }
192 }
193 return true;
194 }
195 }
196}
More advanced text processing for splitting text into lines or tokens.
vr key events use the key codes defined in vr::VRKeys
Definition vr_calib.h:18
bool update_driver_calibration(vr::vr_driver *dp, const std::map< std::string, vr::vr_trackable_state > &target_reference_states) const
update the calibration of a driver from the given target reference states
Definition vr_calib.cxx:31
bool read_calibration(const std::string &file_path, bool update_drivers=true)
read calibration from calibration file
Definition vr_calib.cxx:120
vr_calibration()
constructor is protected to forbid construction of more than one singleton
Definition vr_calib.cxx:117
void update_calibration_info()
iterate vr drivers and copy calibration information into map
Definition vr_calib.cxx:16
bool write_calibration(const std::string &file_path) const
write calibration to calibration file
Definition vr_calib.cxx:179
matrix of fixed size dimensions
Definition fmat.h:23
A vector with zero based index.
Definition fvec.h:26
T normalize()
normalize the vector using the L2-Norm and return the length
Definition fvec.h:302
implements a quaternion.
Definition quaternion.h:21
void put_matrix(mat_type &M) const
compute equivalent 3x3 rotation matrix
Definition quaternion.h:139
void set_driver_calibration_matrix(vr_driver *driver, const float calibration_matrix[12]) const
single point of write access to calibration transformation of vr drivers
Definition vr_driver.cxx:6
interface class for vr drivers.
Definition vr_driver.h:57
void put_calibration_transformation(float transformation_matrix[12]) const
read access to calibration transformation stored as 3x4-matrix
Definition vr_driver.cxx:50
virtual const std::map< std::string, vr_trackable_state > & get_tracking_reference_states() const
provide read only access to tracking reference states
Definition vr_driver.cxx:99
virtual std::string get_driver_name() const =0
return name of driver
void enable_calibration_transformation()
enable use of calibration transformation
Definition vr_driver.cxx:84
virtual std::vector< void * > scan_vr_kits()=0
scan all connected vr kits and return a vector with their ids
bool query_state(vr_kit_state &state, int pose_query=2)
query current state of vr kit and return whether this was successful
Definition vr_kit.cxx:103
vr_calibration & ref_vr_calibration()
access to singleton object of vr_calibration class
Definition vr_calib.cxx:11
void split_to_lines(const char *global_begin, const char *global_end, std::vector< line > &lines, bool truncate_trailing_spaces)
this function splits a text range at the newline characters into single lines.
the cgv namespace
Definition print.h:11
vr_kit * get_vr_kit(void *handle)
query a pointer to a vr kit by its device handle, function can return null pointer in case that no vr...
std::vector< vr_driver * > & get_vr_drivers()
return a vector with all registered vr drivers
@ VRS_TRACKED
trackable is connected and tracked
Definition vr_state.h:88
helper functions to work with poses that can be represented with 3x4 matrix or quaternion plus vector
structure that stores all information describing the state of a VR kit
Definition vr_state.h:139
defines the class vr::vr_driver class and gives access to the driver registry with the functions vr::...