ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ViewTrajectory.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <Logging.h>
11 #include <json/json.h>
12 
13 #include <Eigen/Dense>
14 
15 namespace cloudViewer {
16 namespace visualization {
17 using namespace cloudViewer;
18 
19 const int ViewTrajectory::INTERVAL_MAX = 59;
20 const int ViewTrajectory::INTERVAL_MIN = 0;
21 const int ViewTrajectory::INTERVAL_STEP = 1;
23 
25  if (view_status_.empty()) {
26  return;
27  }
28 
29  // num_of_status is used frequently, give it an alias
30  int n = int(view_status_.size());
31  coeff_.resize(n);
32 
33  // Consider ViewStatus as a point in an 17-dimensional space.
34  for (int i = 0; i < n; i++) {
35  coeff_[i].setZero();
36  coeff_[i].block<17, 1>(0, 0) = view_status_[i].ConvertToVector17d();
37  }
38 
39  // Handle degenerate cases first
40  if (n == 1) {
41  return;
42  } else if (n == 2) {
43  coeff_[0].block<17, 1>(0, 1) =
44  coeff_[1].block<17, 1>(0, 0) - coeff_[0].block<17, 1>(0, 0);
45  coeff_[1].block<17, 1>(0, 1) =
46  coeff_[0].block<17, 1>(0, 0) - coeff_[1].block<17, 1>(0, 0);
47  return;
48  }
49 
50  Eigen::MatrixXd A(n, n);
51  Eigen::VectorXd b(n);
52 
53  // Set matrix A first
54  A.setZero();
55 
56  // Set first and last line
57  if (is_loop_) {
58  A(0, 0) = 4.0;
59  A(0, 1) = 1.0;
60  A(0, n - 1) = 1.0;
61  A(n - 1, 0) = 1.0;
62  A(n - 1, n - 2) = 1.0;
63  A(n - 1, n - 1) = 4.0;
64  } else {
65  A(0, 0) = 2.0;
66  A(0, 1) = 1.0;
67  A(n - 1, n - 2) = 1.0;
68  A(n - 1, n - 1) = 2.0;
69  }
70 
71  // Set middle part
72  for (int i = 1; i < n - 1; i++) {
73  A(i, i) = 4.0;
74  A(i, i - 1) = 1.0;
75  A(i, i + 1) = 1.0;
76  }
77 
78  auto llt_solver = A.llt();
79 
80  for (int k = 0; k < 17; k++) {
81  // Now we work for the k-th coefficient
82  b.setZero();
83 
84  // Set first and last line
85  if (is_loop_) {
86  b(0) = 3.0 * (coeff_[1](k, 0) - coeff_[n - 1](k, 0));
87  b(n - 1) = 3.0 * (coeff_[0](k, 0) - coeff_[n - 2](k, 0));
88  } else {
89  b(0) = 3.0 * (coeff_[1](k, 0) - coeff_[0](k, 0));
90  b(n - 1) = 3.0 * (coeff_[n - 1](k, 0) - coeff_[n - 2](k, 0));
91  }
92 
93  // Set middle part
94  for (int i = 1; i < n - 1; i++) {
95  b(i) = 3.0 * (coeff_[i + 1](k, 0) - coeff_[i - 1](k, 0));
96  }
97 
98  // Solve the linear system
99  Eigen::VectorXd x = llt_solver.solve(b);
100 
101  for (int i = 0; i < n; i++) {
102  int i1 = (i + 1) % n;
103  coeff_[i](k, 1) = x(i);
104  coeff_[i](k, 2) = 3.0 * (coeff_[i1](k, 0) - coeff_[i](k, 0)) -
105  2.0 * x(i) - x(i1);
106  coeff_[i](k, 3) =
107  2.0 * (coeff_[i](k, 0) - coeff_[i1](k, 0)) + x(i) + x(i1);
108  }
109  }
110 }
111 
112 std::tuple<bool, ViewParameters> ViewTrajectory::GetInterpolatedFrame(
113  size_t k) {
114  ViewParameters status;
115  if (view_status_.empty() || k >= NumOfFrames()) {
116  return std::make_tuple(false, status);
117  }
118  size_t segment_index = k / (interval_ + 1);
119  double segment_fraction =
120  double(k - segment_index * (interval_ + 1)) / double(interval_ + 1);
121  Eigen::Vector4d s(1.0, segment_fraction,
122  segment_fraction * segment_fraction,
123  segment_fraction * segment_fraction * segment_fraction);
124  ViewParameters::Vector17d status_in_vector = coeff_[segment_index] * s;
125  status.ConvertFromVector17d(status_in_vector);
126  return std::make_tuple(true, status);
127 }
128 
129 bool ViewTrajectory::ConvertToJsonValue(Json::Value &value) const {
130  Json::Value trajectory_array;
131  for (const auto &status : view_status_) {
132  Json::Value status_object;
133  if (!status.ConvertToJsonValue(status_object)) {
134  return false;
135  }
136  trajectory_array.append(status_object);
137  }
138  value["class_name"] = "ViewTrajectory";
139  value["version_major"] = 1;
140  value["version_minor"] = 0;
141  value["is_loop"] = is_loop_;
142  value["interval"] = interval_;
143  value["trajectory"] = trajectory_array;
144  return true;
145 }
146 
147 bool ViewTrajectory::ConvertFromJsonValue(const Json::Value &value) {
148  if (!value.isObject()) {
150  "ViewTrajectory read JSON failed: unsupported json format.");
151  return false;
152  }
153  if (value.get("class_name", "").asString() != "ViewTrajectory" ||
154  value.get("version_major", 1).asInt() != 1 ||
155  value.get("version_minor", 0).asInt() != 0) {
157  "ViewTrajectory read JSON failed: unsupported json format.");
158  return false;
159  }
160  is_loop_ = value.get("is_loop", false).asBool();
161  interval_ = value.get("interval", 29).asInt();
162  const Json::Value &trajectory_array = value["trajectory"];
163  if (trajectory_array.empty()) {
165  "ViewTrajectory read JSON failed: empty trajectory.");
166  return false;
167  }
168  view_status_.resize(trajectory_array.size());
169  for (int i = 0; i < (int)trajectory_array.size(); i++) {
170  const Json::Value &status_object = trajectory_array[i];
171  ViewParameters status;
172  if (!status.ConvertFromJsonValue(status_object)) {
173  return false;
174  }
175  view_status_[i] = status;
176  }
177  return true;
178 }
179 
180 } // namespace visualization
181 } // namespace cloudViewer
void ConvertFromVector17d(const Vector17d &v)
Eigen::Matrix< double, 17, 1 > Vector17d
bool ConvertFromJsonValue(const Json::Value &value) override
std::vector< ViewParameters::Matrix17x4d, ViewParameters::Matrix17x4d_allocator > coeff_
bool ConvertToJsonValue(Json::Value &value) const override
std::tuple< bool, ViewParameters > GetInterpolatedFrame(size_t k)
std::vector< ViewParameters > view_status_
bool ConvertFromJsonValue(const Json::Value &value) override
#define LogWarning(...)
Definition: Logging.h:72
Generic file read and write utility for python interface.