-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathcamera.cpp
More file actions
143 lines (125 loc) · 4.09 KB
/
Copy pathcamera.cpp
File metadata and controls
143 lines (125 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "sim/camera.h"
#include <math.h>
#include <Eigen/Eigen>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <set>
#include <stdexcept>
#include <tuple>
#include <utility>
#include "mujoco/mjdata.h"
#include "mujoco/mjmodel.h"
#include "mujoco/mujoco.h"
#include "rcs/Robot.h"
namespace rcs {
namespace sim {
SimCameraSet::SimCameraSet(
std::shared_ptr<Sim> sim,
std::unordered_map<std::string, SimCameraConfig> cameras_cfg,
bool render_on_demand)
: sim{sim},
cameras_cfg{cameras_cfg},
buffer{},
buffer_lock{},
cameras{},
render_on_demand{render_on_demand} {
for (auto const& [id, cam] : cameras_cfg) {
this->sim->register_rendering_callback(
[this](const std::string& id, mjrContext& ctx, mjvScene& scene,
mjvOption& opt) { this->frame_callback(id, ctx, scene, opt); },
id, cam.frame_rate, cam.resolution_width, cam.resolution_height);
mjvCamera mjcam;
mjv_defaultCamera(&mjcam);
if (cam.type == CameraType::default_free) {
mjv_defaultFreeCamera(this->sim->m, &mjcam);
} else {
mjcam.type = cam.type;
mjcam.fixedcamid =
mj_name2id(this->sim->m, mjOBJ_CAMERA, cam.identifier.c_str());
}
cameras[id] = mjcam;
}
}
SimCameraSet::~SimCameraSet() {}
int SimCameraSet::buffer_size() {
std::lock_guard<std::mutex> lock(buffer_lock);
return buffer.size();
}
void SimCameraSet::clear_buffer() {
std::lock_guard<std::mutex> lock(buffer_lock);
// when we clear the buffer, there is no last image timestep
this->last_ts = 0;
buffer.clear();
}
std::optional<FrameSet> SimCameraSet::get_latest_frameset() {
if (this->render_on_demand) {
this->render_all();
}
if (buffer.empty()) {
return std::nullopt;
}
std::lock_guard<std::mutex> lock(buffer_lock);
return buffer.back();
}
std::optional<FrameSet> SimCameraSet::get_timestamp_frameset(float ts) {
std::lock_guard<std::mutex> lock(buffer_lock);
for (auto it = buffer.rbegin(); it != buffer.rend(); ++it) {
if (it->timestamp == ts) {
return *it;
}
}
return std::nullopt;
}
void SimCameraSet::render_all() {
for (auto const& [id, cam] : this->cameras_cfg) {
mjrContext* ctx = this->sim->renderer.get_context(id);
this->render_single(id, *ctx, this->sim->renderer.scene,
this->sim->renderer.opt);
}
}
void SimCameraSet::frame_callback(const std::string& id, mjrContext& ctx,
mjvScene& scene, mjvOption& opt) {
if (!this->render_on_demand) {
this->render_single(id, ctx, scene, opt);
}
}
void SimCameraSet::render_single(const std::string& id, mjrContext& ctx,
mjvScene& scene, mjvOption& opt) {
mjrRect viewport = mjr_maxViewport(&ctx);
int W = viewport.width;
int H = viewport.height;
// allocate rgb and depth buffers
ColorFrame frame = ColorFrame::Zero(3 * W * H);
DepthFrame depth = DepthFrame::Zero(1 * W * H);
// update abstract scene
// TODO: we might be able to call this once for all cameras
// there is also a mjv_updateCamera function
mjv_updateScene(this->sim->m, this->sim->d, &opt, NULL, &this->cameras[id],
mjCAT_ALL, &scene);
// mjv_updateCamera(this->sim->m, this->sim->d, &this->cameras[id], &scene);
// render scene in offscreen buffer
mjr_render(viewport, &scene, &ctx);
// read rgb and depth buffers
// depth documentation can be found here:
// https://registry.khronos.org/OpenGL-Refpages/gl4/html/glReadPixels.xhtml
mjr_readPixels(frame.data(), depth.data(), viewport, &ctx);
auto ts = this->sim->d->time;
std::lock_guard<std::mutex> lock(buffer_lock);
// The following code assumes that all render callbacks for a timestep
// happen directly after each other
if (this->last_ts == ts) {
buffer[buffer.size() - 1].color_frames[id] = frame;
buffer[buffer.size() - 1].depth_frames[id] = depth;
} else {
FrameSet fs;
fs.timestamp = ts;
fs.color_frames[id] = frame;
fs.depth_frames[id] = depth;
buffer.push_back(fs);
this->last_ts = ts;
}
}
} // namespace sim
} // namespace rcs