-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add frame impl for future rig support #2698
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
2d8cb75
frame impl.
B1ueber2y 350eb86
update.
B1ueber2y a370d99
formatting.
B1ueber2y bc2414c
update.
B1ueber2y 2f79de6
update.
B1ueber2y 6058852
formatting.
B1ueber2y 873f627
update.
B1ueber2y b679281
Merge branch 'main' into features/frame
B1ueber2y bff7097
formatting.
B1ueber2y 213715d
minor.
B1ueber2y ca7a58c
Merge branch 'main' into features/frame
B1ueber2y ab69299
Merge branch 'main' into features/frame
ahojnnes 374bd9e
Merge branch 'main' into features/frame
B1ueber2y ba36423
Merge branch 'features/frame' of github.com:B1ueber2y/colmap into fea…
B1ueber2y da433a1
update.
B1ueber2y fe58bc1
Merge branch 'main' into features/frame
B1ueber2y 3beb4e2
Merge branch 'main' into features/frame
B1ueber2y 3229804
cr
B1ueber2y c65d577
cr
B1ueber2y d6569a3
merge with main and add some TODOs
B1ueber2y 24f1ce4
cr
B1ueber2y 05d2ade
cr
B1ueber2y b2e5429
cr
B1ueber2y 885593b
fix todos. make frame_from_world optional
B1ueber2y 07cc0ef
include <optional>
B1ueber2y b68160d
cam_from_world_value in pycolmap
B1ueber2y 63055e9
custom structures for sensor_t and data_t
B1ueber2y 7c2959a
Merge branch 'main' into features/frame
B1ueber2y f94cced
cr.
B1ueber2y 4e2f06c
remove the need of sensor_ids
B1ueber2y 068ce06
improve comments
B1ueber2y 0a65a4e
move add sensor to cc
B1ueber2y 4b05f56
minor
B1ueber2y 2be8a14
change the id in data_t from uint64_t to uint32_t
B1ueber2y 355c0a2
fix
B1ueber2y 05f7397
deprecate cam_from_world and always use frame pointer
B1ueber2y 1e72385
minor
B1ueber2y e22e2cd
fix copy construction and assignment for Image class
B1ueber2y ed5aa77
minor fix
B1ueber2y 2519bfa
make clang-tidy happy
B1ueber2y c14fdf6
improve code + add tests for frame.h
B1ueber2y 83fabbd
format
B1ueber2y 9ae245c
update
B1ueber2y 1def428
Merge branch 'main' into features/frame
B1ueber2y 37ce8e6
rename CamFromWorldValue to ComposeCamFromWorld
B1ueber2y 2fa5baf
move RigCalibration to separate file at sensor/rig_calib.h
B1ueber2y File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
// Copyright (c), ETH Zurich and UNC Chapel Hill. | ||
// All rights reserved. | ||
// | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided that the following conditions are met: | ||
// | ||
// * Redistributions of source code must retain the above copyright | ||
// notice, this list of conditions and the following disclaimer. | ||
// | ||
// * Redistributions in binary form must reproduce the above copyright | ||
// notice, this list of conditions and the following disclaimer in the | ||
// documentation and/or other materials provided with the distribution. | ||
// | ||
// * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of | ||
// its contributors may be used to endorse or promote products derived | ||
// from this software without specific prior written permission. | ||
// | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE | ||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
// POSSIBILITY OF SUCH DAMAGE. | ||
|
||
#pragma once | ||
|
||
#include "colmap/geometry/rigid3.h" | ||
#include "colmap/sensor/rig_calib.h" | ||
#include "colmap/util/types.h" | ||
|
||
#include <cstdint> | ||
#include <functional> | ||
#include <map> | ||
#include <memory> | ||
#include <optional> | ||
#include <set> | ||
#include <tuple> | ||
#include <vector> | ||
|
||
namespace colmap { | ||
|
||
struct data_t { | ||
// Unique identifer of the sensor | ||
sensor_t sensor_id; | ||
// Unique identifier of the data (measurement) | ||
// This can be image_t / imu_measurement_t (not supported yet) | ||
uint32_t id; | ||
constexpr data_t(const sensor_t& sensor_id, uint32_t id) | ||
: sensor_id(sensor_id), id(id) {} | ||
|
||
inline bool operator<(const data_t& other) const { | ||
return std::tie(sensor_id, id) < std::tie(other.sensor_id, other.id); | ||
} | ||
inline bool operator==(const data_t& other) const { | ||
return sensor_id == other.sensor_id && id == other.id; | ||
} | ||
inline bool operator!=(const data_t& other) const { | ||
return !(*this == other); | ||
} | ||
}; | ||
constexpr data_t kInvalidDataId = | ||
data_t(kInvalidSensorId, std::numeric_limits<uint32_t>::max()); | ||
|
||
class Frame { | ||
public: | ||
Frame() = default; | ||
|
||
// Access the unique identifier of the frame | ||
inline frame_t FrameId() const; | ||
inline void SetFrameId(frame_t frame_id); | ||
|
||
// Access data ids | ||
inline std::set<data_t>& DataIds(); | ||
inline const std::set<data_t>& DataIds() const; | ||
inline void AddData(data_t data_id); | ||
|
||
// Check whether the data id is existent in the frame | ||
inline bool HasData(data_t data_id) const; | ||
|
||
// Access the rig calibration | ||
inline const std::shared_ptr<class RigCalibration>& RigCalibration() const; | ||
inline void SetRigCalibration( | ||
std::shared_ptr<class RigCalibration> rig_calibration); | ||
// Check if the frame has a non-trivial rig calibration | ||
inline bool HasRigCalibration() const; | ||
|
||
// Access the frame from world transformation | ||
inline const Rigid3d& FrameFromWorld() const; | ||
inline Rigid3d& FrameFromWorld(); | ||
inline const std::optional<Rigid3d>& MaybeFrameFromWorld() const; | ||
inline std::optional<Rigid3d>& MaybeFrameFromWorld(); | ||
inline void SetFrameFromWorld(const Rigid3d& frame_from_world); | ||
inline void SetFrameFromWorld(const std::optional<Rigid3d>& frame_from_world); | ||
inline bool HasPose() const; | ||
inline void ResetPose(); | ||
|
||
// Get the sensor from world transformation | ||
inline Rigid3d SensorFromWorld(sensor_t sensor_id) const; | ||
|
||
private: | ||
frame_t frame_id_ = kInvalidFrameId; | ||
std::set<data_t> data_ids_; | ||
|
||
// Store the frame_from_world transformation and an optional rig calibration. | ||
// If the rig calibration is a nullptr, the frame becomes a single sensor | ||
// case, where rig modeling is no longer needed. | ||
std::optional<Rigid3d> frame_from_world_; | ||
|
||
// [Optional] Rig calibration | ||
std::shared_ptr<class RigCalibration> rig_calibration_ = nullptr; | ||
}; | ||
|
||
//////////////////////////////////////////////////////////////////////////////// | ||
// Implementation | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
frame_t Frame::FrameId() const { return frame_id_; } | ||
|
||
void Frame::SetFrameId(frame_t frame_id) { frame_id_ = frame_id; } | ||
|
||
std::set<data_t>& Frame::DataIds() { return data_ids_; } | ||
|
||
const std::set<data_t>& Frame::DataIds() const { return data_ids_; } | ||
|
||
void Frame::AddData(data_t data_id) { data_ids_.insert(data_id); } | ||
|
||
bool Frame::HasData(data_t data_id) const { | ||
return data_ids_.find(data_id) != data_ids_.end(); | ||
} | ||
|
||
const std::shared_ptr<class RigCalibration>& Frame::RigCalibration() const { | ||
return rig_calibration_; | ||
} | ||
|
||
void Frame::SetRigCalibration( | ||
std::shared_ptr<class RigCalibration> rig_calibration) { | ||
rig_calibration_ = std::move(rig_calibration); | ||
} | ||
|
||
bool Frame::HasRigCalibration() const { | ||
if (!rig_calibration_) | ||
return false; | ||
else | ||
return rig_calibration_->NumSensors() > 1; | ||
} | ||
|
||
const Rigid3d& Frame::FrameFromWorld() const { | ||
THROW_CHECK(frame_from_world_) << "Frame does not have a valid pose."; | ||
return *frame_from_world_; | ||
} | ||
|
||
Rigid3d& Frame::FrameFromWorld() { | ||
THROW_CHECK(frame_from_world_) << "Frame does not have a valid pose."; | ||
return *frame_from_world_; | ||
} | ||
|
||
const std::optional<Rigid3d>& Frame::MaybeFrameFromWorld() const { | ||
return frame_from_world_; | ||
} | ||
|
||
std::optional<Rigid3d>& Frame::MaybeFrameFromWorld() { | ||
return frame_from_world_; | ||
} | ||
|
||
void Frame::SetFrameFromWorld(const Rigid3d& frame_from_world) { | ||
frame_from_world_ = frame_from_world; | ||
} | ||
|
||
void Frame::SetFrameFromWorld(const std::optional<Rigid3d>& frame_from_world) { | ||
frame_from_world_ = frame_from_world; | ||
} | ||
|
||
bool Frame::HasPose() const { return frame_from_world_.has_value(); } | ||
|
||
void Frame::ResetPose() { frame_from_world_.reset(); } | ||
|
||
Rigid3d Frame::SensorFromWorld(sensor_t sensor_id) const { | ||
if (!HasRigCalibration() || rig_calibration_->IsRefSensor(sensor_id)) { | ||
return FrameFromWorld(); | ||
} | ||
THROW_CHECK(rig_calibration_->HasSensor(sensor_id)); | ||
return rig_calibration_->SensorFromRig(sensor_id) * FrameFromWorld(); | ||
} | ||
|
||
} // namespace colmap | ||
|
||
namespace std { | ||
|
||
// [Reference] | ||
// https://stackoverflow.com/questions/26705751/why-is-the-magic-number-in-boosthash-combine-specified-in-hex | ||
template <> | ||
struct hash<colmap::data_t> { | ||
std::size_t operator()(const colmap::data_t& d) const noexcept { | ||
size_t h1 = | ||
std::hash<uint64_t>{}(std::hash<colmap::sensor_t>{}(d.sensor_id)); | ||
size_t h2 = std::hash<uint64_t>{}(d.id); | ||
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); | ||
} | ||
}; | ||
|
||
} // namespace std |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright (c), ETH Zurich and UNC Chapel Hill. | ||
// All rights reserved. | ||
// | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided that the following conditions are met: | ||
// | ||
// * Redistributions of source code must retain the above copyright | ||
// notice, this list of conditions and the following disclaimer. | ||
// | ||
// * Redistributions in binary form must reproduce the above copyright | ||
// notice, this list of conditions and the following disclaimer in the | ||
// documentation and/or other materials provided with the distribution. | ||
// | ||
// * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of | ||
// its contributors may be used to endorse or promote products derived | ||
// from this software without specific prior written permission. | ||
// | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE | ||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
// POSSIBILITY OF SUCH DAMAGE. | ||
|
||
#include "colmap/scene/frame.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace colmap { | ||
namespace { | ||
|
||
Rigid3d TestRigid3d() { | ||
return Rigid3d(Eigen::Quaterniond::UnitRandom(), Eigen::Vector3d::Random()); | ||
} | ||
|
||
TEST(Frame, Default) { | ||
Frame frame; | ||
EXPECT_EQ(frame.FrameId(), kInvalidFrameId); | ||
EXPECT_FALSE(frame.HasPose()); | ||
EXPECT_FALSE(frame.HasRigCalibration()); | ||
} | ||
|
||
TEST(Frame, SetUp) { | ||
sensor_t s1(SensorType::IMU, 0); | ||
sensor_t s2(SensorType::CAMERA, 0); | ||
std::shared_ptr<RigCalibration> calib = std::make_shared<RigCalibration>(); | ||
calib->AddRefSensor(s1); | ||
calib->AddSensor(s2, TestRigid3d()); | ||
|
||
Frame frame; | ||
frame.AddData(data_t(s1, 2)); | ||
frame.AddData(data_t(s2, 5)); | ||
frame.SetRigCalibration(calib); | ||
EXPECT_TRUE(frame.HasRigCalibration()); | ||
EXPECT_FALSE(frame.HasPose()); | ||
} | ||
|
||
TEST(Frame, SetResetPose) { | ||
Frame frame; | ||
EXPECT_FALSE(frame.HasPose()); | ||
EXPECT_ANY_THROW(frame.FrameFromWorld()); | ||
frame.SetFrameFromWorld(Rigid3d()); | ||
EXPECT_TRUE(frame.HasPose()); | ||
EXPECT_EQ(frame.FrameFromWorld().rotation.coeffs(), | ||
Eigen::Quaterniond::Identity().coeffs()); | ||
EXPECT_EQ(frame.FrameFromWorld().translation, Eigen::Vector3d::Zero()); | ||
frame.ResetPose(); | ||
EXPECT_FALSE(frame.HasPose()); | ||
EXPECT_ANY_THROW(frame.FrameFromWorld()); | ||
} | ||
|
||
} // namespace | ||
} // namespace colmap |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.