xref: /aosp_15_r20/external/dynamic_depth/internal/dynamic_depth/earth_pose.cc (revision a62be0856e8e1158f43b03e41bbad10f4d005fde)
1 #include "dynamic_depth/earth_pose.h"
2 
3 #include <math.h>
4 
5 #include <cmath>
6 
7 #include "android-base/logging.h"
8 #include "dynamic_depth/const.h"
9 
10 using ::dynamic_depth::xmpmeta::xml::Deserializer;
11 using ::dynamic_depth::xmpmeta::xml::Serializer;
12 
13 namespace dynamic_depth {
14 namespace {
15 
16 const char kLatitude[] = "Latitude";
17 const char kLongitude[] = "Longitude";
18 const char kAltitude[] = "Altitude";
19 const char kRotationX[] = "RotationX";
20 const char kRotationY[] = "RotationY";
21 const char kRotationZ[] = "RotationZ";
22 const char kRotationW[] = "RotationW";
23 const char kTimestamp[] = "Timestamp";
24 const char kNamespaceHref[] = "http://ns.google.com/photos/dd/1.0/earthpose/";
25 
NormalizeQuaternion(const std::vector<float> & quat)26 const std::vector<float> NormalizeQuaternion(const std::vector<float>& quat) {
27   if (quat.size() < 4) {
28     return std::vector<float>();
29   }
30   float length = std::sqrt((quat[0] * quat[0]) + (quat[1] * quat[1]) +
31                            (quat[2] * quat[2])) +
32                  (quat[3] * quat[3]);
33   const std::vector<float> normalized = {quat[0] / length, quat[1] / length,
34                                          quat[2] / length, quat[3] / length};
35   return normalized;
36 }
37 
38 }  // namespace
39 
40 // Private constructor.
EarthPose()41 EarthPose::EarthPose() : timestamp_(-1) {}
42 
43 // Public methods.
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)44 void EarthPose::GetNamespaces(
45     std::unordered_map<string, string>* ns_name_href_map) {
46   if (ns_name_href_map == nullptr) {
47     LOG(ERROR) << "Namespace list or own namespace is null";
48     return;
49   }
50   ns_name_href_map->emplace(DynamicDepthConst::EarthPose(), kNamespaceHref);
51 }
52 
FromData(const std::vector<double> & position,const std::vector<float> & orientation,const int64 timestamp)53 std::unique_ptr<EarthPose> EarthPose::FromData(
54     const std::vector<double>& position, const std::vector<float>& orientation,
55     const int64 timestamp) {
56   if (position.empty() && orientation.empty()) {
57     LOG(ERROR) << "Either position or orientation must be provided";
58     return nullptr;
59   }
60 
61   std::unique_ptr<EarthPose> earth_pose(new EarthPose());
62   if (position.size() >= 3) {
63     earth_pose->position_ = position;
64   }
65 
66   if (orientation.size() >= 4) {
67     earth_pose->orientation_ = NormalizeQuaternion(orientation);
68   }
69 
70   if (timestamp >= 0) {
71     earth_pose->timestamp_ = timestamp;
72   }
73 
74   return earth_pose;
75 }
76 
FromDeserializer(const Deserializer & parent_deserializer)77 std::unique_ptr<EarthPose> EarthPose::FromDeserializer(
78     const Deserializer& parent_deserializer) {
79   std::unique_ptr<Deserializer> deserializer =
80       parent_deserializer.CreateDeserializer(
81           DynamicDepthConst::Namespace(DynamicDepthConst::EarthPose()),
82           DynamicDepthConst::EarthPose());
83   if (deserializer == nullptr) {
84     return nullptr;
85   }
86   std::unique_ptr<EarthPose> earth_pose(new EarthPose());
87   if (!earth_pose->ParseEarthPoseFields(*deserializer)) {
88     return nullptr;
89   }
90   return earth_pose;
91 }
92 
HasPosition() const93 bool EarthPose::HasPosition() const { return position_.size() == 3; }
HasOrientation() const94 bool EarthPose::HasOrientation() const { return orientation_.size() == 4; }
95 
GetPosition() const96 const std::vector<double>& EarthPose::GetPosition() const { return position_; }
97 
GetOrientation() const98 const std::vector<float>& EarthPose::GetOrientation() const {
99   return orientation_;
100 }
101 
GetTimestamp() const102 int64 EarthPose::GetTimestamp() const { return timestamp_; }
103 
Serialize(Serializer * serializer) const104 bool EarthPose::Serialize(Serializer* serializer) const {
105   if (serializer == nullptr) {
106     LOG(ERROR) << "Serializer is null";
107     return false;
108   }
109 
110   if (!HasPosition() && !HasOrientation()) {
111     LOG(ERROR) << "Device pose has neither position nor orientation";
112     return false;
113   }
114 
115   bool success = true;
116   if (position_.size() == 3) {
117     success &=
118         serializer->WriteProperty(DynamicDepthConst::EarthPose(), kLatitude,
119                                   std::to_string(position_[0])) &&
120         serializer->WriteProperty(DynamicDepthConst::EarthPose(), kLongitude,
121                                   std::to_string(position_[1])) &&
122         serializer->WriteProperty(DynamicDepthConst::EarthPose(), kAltitude,
123                                   std::to_string(position_[2]));
124   }
125 
126   if (orientation_.size() == 4) {
127     success &=
128         serializer->WriteProperty(DynamicDepthConst::EarthPose(), kRotationX,
129                                   std::to_string(orientation_[0])) &&
130         serializer->WriteProperty(DynamicDepthConst::EarthPose(), kRotationY,
131                                   std::to_string(orientation_[1])) &&
132         serializer->WriteProperty(DynamicDepthConst::EarthPose(), kRotationZ,
133                                   std::to_string(orientation_[2])) &&
134         serializer->WriteProperty(DynamicDepthConst::EarthPose(), kRotationW,
135                                   std::to_string(orientation_[3]));
136   }
137 
138   if (timestamp_ >= 0) {
139     serializer->WriteProperty(DynamicDepthConst::EarthPose(), kTimestamp,
140                               std::to_string(timestamp_));
141   }
142 
143   return success;
144 }
145 
146 // Private methods.
ParseEarthPoseFields(const Deserializer & deserializer)147 bool EarthPose::ParseEarthPoseFields(const Deserializer& deserializer) {
148   double lat, lon, alt;
149   // If a position field is present, the rest must be as well.
150   if (deserializer.ParseDouble(DynamicDepthConst::EarthPose(), kLatitude,
151                                &lat)) {
152     if (!deserializer.ParseDouble(DynamicDepthConst::EarthPose(), kLongitude,
153                                   &lon)) {
154       return false;
155     }
156     if (!deserializer.ParseDouble(DynamicDepthConst::EarthPose(), kAltitude,
157                                   &alt)) {
158       return false;
159     }
160     position_ = {lat, lon, alt};
161   }
162 
163   // Same for orientation.
164   float x, y, z, w;
165   if (deserializer.ParseFloat(DynamicDepthConst::EarthPose(), kRotationX, &x)) {
166     if (!deserializer.ParseFloat(DynamicDepthConst::EarthPose(), kRotationY,
167                                  &y)) {
168       return false;
169     }
170     if (!deserializer.ParseFloat(DynamicDepthConst::EarthPose(), kRotationZ,
171                                  &z)) {
172       return false;
173     }
174     if (!deserializer.ParseFloat(DynamicDepthConst::EarthPose(), kRotationW,
175                                  &w)) {
176       return false;
177     }
178     orientation_ = std::vector<float>({x, y, z, w});
179   }
180 
181   if (position_.size() < 3 && orientation_.size() < 4) {
182     return false;
183   }
184 
185   deserializer.ParseLong(DynamicDepthConst::EarthPose(), kTimestamp,
186                          &timestamp_);
187   return true;
188 }
189 
190 }  // namespace dynamic_depth
191