Skip to content

Expose camera sensor temperature#1775

Open
jakgra wants to merge 2 commits into
developfrom
expose_sensor_temp
Open

Expose camera sensor temperature#1775
jakgra wants to merge 2 commits into
developfrom
expose_sensor_temp

Conversation

@jakgra
Copy link
Copy Markdown
Contributor

@jakgra jakgra commented Apr 29, 2026

Summary by CodeRabbit

  • New Features

    • Added sensor temperature retrieval from camera frames. Users can now access the camera's sensor temperature in degrees Celsius through the new getSensorTemperature() method on both encoded and image frames. Temperature returns NaN when unavailable.
  • Tests

    • Added validation tests for sensor temperature functionality.

@jakgra jakgra requested a review from moratom April 29, 2026 16:15
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

Warning

Rate limit exceeded

@jakgra has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 53 minutes and 7 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 54003d55-ccbb-41a4-a558-7281f7c82af8

📥 Commits

Reviewing files that changed from the base of the PR and between 4979d9d and 814ae0c.

📒 Files selected for processing (2)
  • cmake/Depthai/DepthaiDeviceRVC4Config.cmake
  • cmake/Depthai/DepthaiDeviceSideConfig.cmake
📝 Walkthrough

Walkthrough

A new sensor temperature field is added across the codebase. The sensorTemperatureC field is introduced to protobuf's CameraSettings message, with corresponding getSensorTemperature() getters added to both EncodedFrame and ImgFrame classes. Serialization logic is updated to handle the new field, Python bindings expose the new methods, and tests validate the functionality.

Changes

Cohort / File(s) Summary
Core Header Declarations
include/depthai/pipeline/datatype/EncodedFrame.hpp, include/depthai/pipeline/datatype/ImgFrame.hpp
Added getSensorTemperature() const method declarations to both frame classes. ImgFrame header also extends CameraSettings metadata to include sensorTemperatureC field initialized to NaN, with <limits> include added.
Core Implementation
src/pipeline/datatype/EncodedFrame.cpp, src/pipeline/datatype/ImgFrame.cpp
Implemented getSensorTemperature() getter methods returning the sensor temperature from the camera settings metadata.
Serialization
protos/common.proto, src/utility/ProtoSerialize.cpp
Added sensorTemperatureC float field to protobuf CameraSettings message. Updated serialization/deserialization logic to convert between C++ frame objects and protobuf representation for both EncodedFrame and ImgFrame.
Python Bindings
bindings/python/src/pipeline/datatype/EncodedFrameBindings.cpp, bindings/python/src/pipeline/datatype/ImgFrameBindings.cpp
Added pybind11 method bindings for getSensorTemperature() to expose the C++ getters to Python API.
Tests & Examples
tests/src/onhost_tests/pipeline/datatype/imgframe_test.cpp, examples/cpp/Camera/camera_multiple_outputs.cpp
Updated ImgFrame test to validate sensorTemperatureC metadata handling and getSensorTemperature() return value. Fixed trailing newline in example file.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested labels

testable

Suggested reviewers

  • moratom

Poem

🐰 A rabbit hopped through data streams so bright,
Adding temperature where cameras take their sight,
Through proto fields and getters, C++ and Py,
Sensor warmth now flows across the sky! 🌡️✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Expose camera sensor temperature' accurately and clearly describes the main change: adding sensor temperature access through new getter methods across Python bindings, C++ headers, and implementations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch expose_sensor_temp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 53 minutes and 7 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/src/onhost_tests/pipeline/datatype/imgframe_test.cpp (1)

105-131: ⚠️ Potential issue | 🟡 Minor

Add an explicit test for the “unavailable temperature” path.

Current additions validate set/copy behavior, but not the documented default (NaN when unavailable). Please add one assertion for a fresh ImgFrame with no temperature set.

✅ Suggested test addition
 TEST_CASE("ImgFrame timestamps and camera settings", "[ImgFrame][Timestamps]") {
     dai::ImgFrame frame;
+    SECTION("Sensor temperature defaults to NaN when unavailable") {
+        REQUIRE(std::isnan(frame.getSensorTemperature()));
+    }
     auto now = std::chrono::steady_clock::now();

Also applies to: 177-200

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/src/onhost_tests/pipeline/datatype/imgframe_test.cpp` around lines 105
- 131, A fresh ImgFrame should return NaN for unavailable sensor temperature—add
an assertion that a default-constructed dai::ImgFrame (no temperature set)
yields NaN from getSensorTemperature(); implement this by creating a new
ImgFrame (or reusing one after reset) and asserting
std::isnan(frame.getSensorTemperature()) (or using Catch's
REQUIRE(std::isnan(...))) near the other temperature checks; do the same for the
other similar test block that starts around the second occurrence mentioned.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@protos/common.proto`:
- Line 27: Change the proto scalar field sensorTemperatureC in
protos/common.proto to be optional so presence can be tracked (replace the
non-optional float with an optional float); then update the deserialization
logic in ProtoSerialize.cpp that populates obj.cam.sensorTemperatureC to check
presence via imgFrame->cam().has_sensortemperaturec() and, when absent, set
obj.cam.sensorTemperatureC to std::numeric_limits<float>::quiet_NaN() (matching
the ImgFrame.hpp initialization) instead of using the default 0.0.

---

Outside diff comments:
In `@tests/src/onhost_tests/pipeline/datatype/imgframe_test.cpp`:
- Around line 105-131: A fresh ImgFrame should return NaN for unavailable sensor
temperature—add an assertion that a default-constructed dai::ImgFrame (no
temperature set) yields NaN from getSensorTemperature(); implement this by
creating a new ImgFrame (or reusing one after reset) and asserting
std::isnan(frame.getSensorTemperature()) (or using Catch's
REQUIRE(std::isnan(...))) near the other temperature checks; do the same for the
other similar test block that starts around the second occurrence mentioned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 873ea51d-edd6-43a2-bf18-e3c08ca0e787

📥 Commits

Reviewing files that changed from the base of the PR and between f1b6dfc and 4979d9d.

📒 Files selected for processing (10)
  • bindings/python/src/pipeline/datatype/EncodedFrameBindings.cpp
  • bindings/python/src/pipeline/datatype/ImgFrameBindings.cpp
  • examples/cpp/Camera/camera_multiple_outputs.cpp
  • include/depthai/pipeline/datatype/EncodedFrame.hpp
  • include/depthai/pipeline/datatype/ImgFrame.hpp
  • protos/common.proto
  • src/pipeline/datatype/EncodedFrame.cpp
  • src/pipeline/datatype/ImgFrame.cpp
  • src/utility/ProtoSerialize.cpp
  • tests/src/onhost_tests/pipeline/datatype/imgframe_test.cpp
📜 Review details
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2026-03-24T22:39:04.364Z
Learnt from: MaticTonin
Repo: luxonis/depthai-core PR: 1732
File: src/pipeline/Pipeline.cpp:705-705
Timestamp: 2026-03-24T22:39:04.364Z
Learning: Do not flag the `!= ""` part of the auto-calibration condition as redundant when it appears in `PipelineImpl::build()` (or closely related pipeline build logic). If the code uses `utility::getEnvAs<std::string>(..., default)` with a default such as `"ON_START"`, the explicit empty-string guard may still be intentional to treat an explicitly empty env var as “OFF/disabled” (or to avoid special-casing elsewhere). Only consider removing `!= ""` if the codebase has an explicit, enforceable guarantee that `DEPTHAI_AUTOCALIBRATION` can never be set to an empty string (e.g., via validated parsing/CI checks); otherwise, keep the guard.

Applied to files:

  • src/pipeline/datatype/EncodedFrame.cpp
  • src/pipeline/datatype/ImgFrame.cpp
📚 Learning: 2026-03-23T09:35:30.339Z
Learnt from: aljazkonec1
Repo: luxonis/depthai-core PR: 1728
File: protos/common.proto:20-25
Timestamp: 2026-03-23T09:35:30.339Z
Learning: In luxonis/depthai-core’s `protos/common.proto`, do not change existing enumerator values for the public `LengthUnit` and `CameraBoardSocket` enums, and do not prepend new zero-value entries like `UNSPECIFIED`. These enums are already released as public API and are used in serialized data; altering numeric values or changing the first/zero member will break backward compatibility with existing user code and stored/serialized representations.

Applied to files:

  • protos/common.proto
📚 Learning: 2026-03-23T09:35:34.824Z
Learnt from: aljazkonec1
Repo: luxonis/depthai-core PR: 1728
File: protos/common.proto:20-25
Timestamp: 2026-03-23T09:35:34.824Z
Learning: In the depthai-core repository (luxonis/depthai-core), the `LengthUnit` and `CameraBoardSocket` enums (defined in both C++ headers and `protos/common.proto`) are already released as public API and must not have their existing enumerator values changed or have new zero-value "UNSPECIFIED" entries prepended, as that would break existing user code and serialized data.

Applied to files:

  • src/utility/ProtoSerialize.cpp
📚 Learning: 2026-04-20T14:47:11.304Z
Learnt from: aljazkonec1
Repo: luxonis/depthai-core PR: 1760
File: tests/src/ondevice_tests/script_node_test.cpp:631-689
Timestamp: 2026-04-20T14:47:11.304Z
Learning: In `tests/src/ondevice_tests/script_node_test.cpp` (depthai-core), the `NNData roundtrip in Script node` test is intentionally a metadata-only test that validates `TensorInfo` fields (datatype, order, dims, strides, quantization params, etc.). Payload/element-wise value validation for NNData tensors is handled in a separate dedicated test. Do not flag the absence of payload assertions in this test case.

Applied to files:

  • tests/src/onhost_tests/pipeline/datatype/imgframe_test.cpp
🔇 Additional comments (8)
examples/cpp/Camera/camera_multiple_outputs.cpp (1)

151-151: Formatting-only change looks good.

This is a safe newline-at-EOF normalization with no behavioral impact.

bindings/python/src/pipeline/datatype/ImgFrameBindings.cpp (1)

255-255: Binding addition is clean and consistent.

ImgFrame.getSensorTemperature() is exposed in the expected getter block with doc wiring.

src/pipeline/datatype/EncodedFrame.cpp (1)

52-54: Getter implementation is straightforward and correct.

Directly returning cam.sensorTemperatureC matches the new metadata field contract.

src/pipeline/datatype/ImgFrame.cpp (1)

142-145: Getter implementation is consistent with the rest of ImgFrame.

No issues in this addition.

include/depthai/pipeline/datatype/EncodedFrame.hpp (1)

95-99: Public API addition is clear and well-placed.

Declaration and docstring are consistent with neighboring getters.

bindings/python/src/pipeline/datatype/EncodedFrameBindings.cpp (1)

91-91: Python binding extension looks good.

EncodedFrame.getSensorTemperature() is correctly exposed alongside related getters.

include/depthai/pipeline/datatype/ImgFrame.hpp (1)

4-4: Header updates are cohesive and correctly wired.

NaN default initialization plus serialization and getter declaration are aligned.

Also applies to: 213-217, 748-750

src/utility/ProtoSerialize.cpp (1)

646-646: Consistent sensorTemperatureC round-trip wiring looks correct.

The new field is mapped in both directions for ImgFrame and EncodedFrame, including helper paths used by RGBDData, so sensor temperature metadata is preserved across protobuf serialization/deserialization.

Also applies to: 707-707, 971-971, 1020-1020, 1109-1109

Comment thread protos/common.proto
CameraFsync fsync = 6;
int32 sensorMode = 7;
float fps = 8;
float sensorTemperatureC = 9;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Verify proto declaration"
rg -nP 'sensorTemperatureC\s*=\s*9' protos/common.proto

echo "2) Verify serialization/deserialization handling"
rg -n 'sensorTemperatureC|sensortemperaturec|has_sensortemperaturec' src/utility/ProtoSerialize.cpp

echo "Expected: deserialization path should gate assignment with has_sensortemperaturec(), otherwise missing field becomes 0.0."

Repository: luxonis/depthai-core

Length of output: 665


🏁 Script executed:

# Check the context around deserialization lines to understand the current implementation
head -n 980 src/utility/ProtoSerialize.cpp | tail -n 20

Repository: luxonis/depthai-core

Length of output: 1026


🏁 Script executed:

# Look for documentation about sensorTemperatureC contract
rg -i 'unavailable|nan|quiet_nan' src/utility/ProtoSerialize.cpp -B 2 -A 2

Repository: luxonis/depthai-core

Length of output: 46


🏁 Script executed:

# Check if there are other optional fields in the proto to understand the pattern
rg -n 'optional' protos/common.proto

Repository: luxonis/depthai-core

Length of output: 107


🏁 Script executed:

# Search for how other temperature or sensor fields handle unavailable values
rg -i 'temperature' protos/common.proto -B 1 -A 1

Repository: luxonis/depthai-core

Length of output: 119


🏁 Script executed:

# Search for the cam struct definition and any documentation about sensorTemperatureC
rg -n 'sensorTemperatureC' --type cpp --type hpp --type h -B 3 -A 3

Repository: luxonis/depthai-core

Length of output: 92


🏁 Script executed:

# Look for header file definitions of the camera metadata structure
fd -e hpp -e h | xargs rg -l 'sensorTemperatureC' 2>/dev/null || echo "No matches in header files"

Repository: luxonis/depthai-core

Length of output: 111


🏁 Script executed:

# Search for any comments or documentation about unavailable temperature values
rg -i 'temperature.*unavailable|unavailable.*temperature|nan.*temperature|temperature.*nan' --type cpp --type hpp --type h

Repository: luxonis/depthai-core

Length of output: 92


🏁 Script executed:

# Read the ImgFrame header to understand the sensorTemperatureC field
cat -n include/depthai/pipeline/datatype/ImgFrame.hpp | grep -A 10 -B 10 'sensorTemperatureC'

Repository: luxonis/depthai-core

Length of output: 1057


🏁 Script executed:

# Also search for any documentation in comments about temperature or "unavailable"
rg -n 'unavailable|quiet_NaN|quiet_nan' include/depthai/pipeline/datatype/ImgFrame.hpp

Repository: luxonis/depthai-core

Length of output: 144


🏁 Script executed:

# Look at the proto definition more thoroughly to see if there are comments
cat -n protos/common.proto | grep -A 5 -B 5 'sensorTemperatureC'

Repository: luxonis/depthai-core

Length of output: 403


🏁 Script executed:

# Verify the exact deserialization pattern and confirm no presence checks are used
cat -n src/utility/ProtoSerialize.cpp | sed -n '968,975p'

Repository: luxonis/depthai-core

Length of output: 452


🏁 Script executed:

# Check other deserialization instances (lines 1020, 1109) to see if they have the same issue
cat -n src/utility/ProtoSerialize.cpp | sed -n '1017,1024p'

Repository: luxonis/depthai-core

Length of output: 531


Make sensorTemperatureC optional and preserve NaN semantics in deserialization.

The C++ struct initializes sensorTemperatureC to quiet_NaN() (ImgFrame.hpp:748) to represent unavailable values. However, the proto3 field at line 27 is a non-optional scalar, which cannot distinguish between absent and zero. When deserialized, missing fields become 0.0, overwriting the NaN semantics.

The proto field must be declared as optional to enable presence tracking:

Proto change
-    float sensorTemperatureC = 9;
+    optional float sensorTemperatureC = 9;

Additionally, deserialization at ProtoSerialize.cpp lines 971 and 1020 must check presence and preserve the NaN default when the field is absent:

obj.cam.sensorTemperatureC = imgFrame->cam().has_sensortemperaturec() 
    ? imgFrame->cam().sensortemperaturec() 
    : std::numeric_limits<float>::quiet_NaN();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protos/common.proto` at line 27, Change the proto scalar field
sensorTemperatureC in protos/common.proto to be optional so presence can be
tracked (replace the non-optional float with an optional float); then update the
deserialization logic in ProtoSerialize.cpp that populates
obj.cam.sensorTemperatureC to check presence via
imgFrame->cam().has_sensortemperaturec() and, when absent, set
obj.cam.sensorTemperatureC to std::numeric_limits<float>::quiet_NaN() (matching
the ImgFrame.hpp initialization) instead of using the default 0.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant