Skip to content

Commit 84892b4

Browse files
saulthuxlz
authored andcommitted
Add exposure control of the color camera
1 parent ae39a6d commit 84892b4

File tree

6 files changed

+281
-0
lines changed

6 files changed

+281
-0
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ SET(SOURCES
123123
include/libfreenect2/frame_listener.hpp
124124
include/libfreenect2/frame_listener_impl.h
125125
include/libfreenect2/libfreenect2.hpp
126+
include/libfreenect2/color_settings.h
126127
include/libfreenect2/packet_pipeline.h
127128
include/internal/libfreenect2/packet_processor.h
128129
include/libfreenect2/registration.h

include/internal/libfreenect2/protocol/command.h

+36
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define COMMAND_H_
2929

3030
#include <stdint.h>
31+
#include <cstring>
3132
#include "libfreenect2/protocol/response.h"
3233

3334
#define KCMD_READ_FIRMWARE_VERSIONS 0x02
@@ -40,6 +41,8 @@
4041
#define KCMD_SET_STREAMING 0x2B
4142
#define KCMD_SET_MODE 0x4B
4243

44+
#define KCMD_RGB_SETTING 0x3E // Command value for color camera settings
45+
4346
#define KCMD_0x46 0x46
4447
#define KCMD_0x47 0x47
4548

@@ -219,6 +222,39 @@ typedef CommandWith4Params<KCMD_SET_MODE, 0x00, 0x00> SetModeDisabledCommand;
219222
typedef CommandWith4Params<KCMD_SET_MODE, 0x00, 0x01> SetModeEnabledCommand;
220223
typedef CommandWith4Params<KCMD_SET_MODE, 0x00, 0x01, 0x00640064> SetModeEnabledWith0x00640064Command;
221224
typedef CommandWith4Params<KCMD_SET_MODE, 0x00, 0x01, 0x00500050> SetModeEnabledWith0x00500050Command;
225+
226+
// The following information was found by using the library released by Microsoft under MIT license,
227+
// https://github.com/Microsoft/MixedRealityCompanionKit/tree/master/KinectIPD/NuiSensor
228+
// Command values come from headers, packet CommandId from stepping through assembly in NuiSensorLib.lib
229+
#define ColorSettingResponseSize sizeof(ColorSettingResponse)
230+
struct ColorSettingCommand : public Command<KCMD_RGB_SETTING, ColorSettingResponseSize, ColorSettingResponseSize, 4>
231+
{
232+
ColorSettingCommand(ColorSettingCommandType cmd, uint32_t value = 0)
233+
: Command<KCMD_RGB_SETTING, ColorSettingResponseSize, ColorSettingResponseSize, 4>(0) // seq always zero
234+
{
235+
// Data parameters are elements of struct NUISENSOR_RGB_CHANGE_STREAM_SETTING
236+
// which supports multiple settings for a single call.
237+
this->data_.parameters[0] = 1; // NumCommands = 1 for single command
238+
this->data_.parameters[1] = 0; // SequenceId = 0 for RGB commands
239+
this->data_.parameters[2] = (uint32_t)cmd; // Cmd with a value from NUISENSOR_RGB_COMMAND_*
240+
this->data_.parameters[3] = value; // Arg is int or float depending on Cmd, zero for GET_*
241+
}
242+
243+
// Could overload ctor to ease usage for float-valued settings.
244+
ColorSettingCommand(ColorSettingCommandType cmd, float value)
245+
: ColorSettingCommand(cmd, float_bytes_to_uint32_(value))
246+
{
247+
}
248+
249+
private:
250+
static uint32_t float_bytes_to_uint32_(float value)
251+
{
252+
uint32_t out;
253+
memcpy(&out, &value, sizeof(out));
254+
return out;
255+
}
256+
};
257+
222258
} /* namespace protocol */
223259
} /* namespace libfreenect2 */
224260
#endif /* COMMAND_H_ */

include/internal/libfreenect2/protocol/response.h

+12
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,18 @@ LIBFREENECT2_PACK(struct P0TablesResponse
323323
uint8_t unknownD[];
324324
});
325325

326+
// RGB camera settings reply for a single setting change.
327+
// Equivalent of NUISENSOR_RGB_CHANGE_STREAM_SETTING_REPLY in NuiSensorLib.h
328+
LIBFREENECT2_PACK(struct ColorSettingResponse
329+
{
330+
uint32_t NumStatus;
331+
uint32_t CommandListStatus;
332+
// Result of the first command -- we only send one at a time for now.
333+
// Equivalent of a fixed-length array of NUISENSOR_RGB_CHANGE_STREAM_SETTING_REPLY_STATUS in NuiSensorLib.h
334+
uint32_t Status;
335+
uint32_t Data;
336+
});
337+
326338
} /* namespace protocol */
327339
} /* namespace libfreenect2 */
328340
#endif /* RESPONSE_H_ */

include/libfreenect2/color_settings.h

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* This file is part of the OpenKinect Project. http://www.openkinect.org
3+
*
4+
* Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file
5+
* for details.
6+
*
7+
* This code is licensed to you under the terms of the Apache License, version
8+
* 2.0, or, at your option, the terms of the GNU General Public License,
9+
* version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
10+
* or the following URLs:
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
* http://www.gnu.org/licenses/gpl-2.0.txt
13+
*
14+
* If you redistribute this file in source form, modified or unmodified, you
15+
* may:
16+
* 1) Leave this header intact and distribute it under the same terms,
17+
* accompanying it with the APACHE20 and GPL20 files, or
18+
* 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
19+
* 3) Delete the GPL v2 clause and accompany it with the APACHE20 file
20+
* In all cases you must keep the copyright notice intact and include a copy
21+
* of the CONTRIB file.
22+
*
23+
* Binary distributions must follow the binary distribution requirements of
24+
* either License.
25+
*/
26+
27+
#ifndef COLOR_SETTINGS_H_
28+
#define COLOR_SETTINGS_H_
29+
30+
namespace libfreenect2
31+
{
32+
33+
// The following information was found by using the library released by Microsoft under MIT license,
34+
// https://github.com/Microsoft/MixedRealityCompanionKit/tree/master/KinectIPD/NuiSensor
35+
enum ColorSettingCommandType
36+
{
37+
COLOR_SETTING_SET_EXPOSURE_MODE = 0,
38+
COLOR_SETTING_SET_INTEGRATION_TIME = 1,
39+
COLOR_SETTING_GET_INTEGRATION_TIME = 2,
40+
COLOR_SETTING_SET_WHITE_BALANCE_MODE = 10,
41+
COLOR_SETTING_SET_RED_CHANNEL_GAIN = 11,
42+
COLOR_SETTING_SET_GREEN_CHANNEL_GAIN = 12,
43+
COLOR_SETTING_SET_BLUE_CHANNEL_GAIN = 13,
44+
COLOR_SETTING_GET_RED_CHANNEL_GAIN = 14,
45+
COLOR_SETTING_GET_GREEN_CHANNEL_GAIN = 15,
46+
COLOR_SETTING_GET_BLUE_CHANNEL_GAIN = 16,
47+
COLOR_SETTING_SET_EXPOSURE_TIME_MS = 17,
48+
COLOR_SETTING_GET_EXPOSURE_TIME_MS = 18,
49+
COLOR_SETTING_SET_DIGITAL_GAIN = 19,
50+
COLOR_SETTING_GET_DIGITAL_GAIN = 20,
51+
COLOR_SETTING_SET_ANALOG_GAIN = 21,
52+
COLOR_SETTING_GET_ANALOG_GAIN = 22,
53+
COLOR_SETTING_SET_EXPOSURE_COMPENSATION = 23,
54+
COLOR_SETTING_GET_EXPOSURE_COMPENSATION = 24,
55+
COLOR_SETTING_SET_ACS = 25,
56+
COLOR_SETTING_GET_ACS = 26,
57+
COLOR_SETTING_SET_EXPOSURE_METERING_MODE = 27,
58+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONES = 28,
59+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_0_WEIGHT = 29,
60+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_1_WEIGHT = 30,
61+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_2_WEIGHT = 31,
62+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_3_WEIGHT = 32,
63+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_4_WEIGHT = 33,
64+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_5_WEIGHT = 34,
65+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_6_WEIGHT = 35,
66+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_7_WEIGHT = 36,
67+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_8_WEIGHT = 37,
68+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_9_WEIGHT = 38,
69+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_10_WEIGHT = 39,
70+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_11_WEIGHT = 40,
71+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_12_WEIGHT = 41,
72+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_13_WEIGHT = 42,
73+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_14_WEIGHT = 43,
74+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_15_WEIGHT = 44,
75+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_16_WEIGHT = 45,
76+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_17_WEIGHT = 46,
77+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_18_WEIGHT = 47,
78+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_19_WEIGHT = 48,
79+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_20_WEIGHT = 49,
80+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_21_WEIGHT = 50,
81+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_22_WEIGHT = 51,
82+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_23_WEIGHT = 52,
83+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_24_WEIGHT = 53,
84+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_25_WEIGHT = 54,
85+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_26_WEIGHT = 55,
86+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_27_WEIGHT = 56,
87+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_28_WEIGHT = 57,
88+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_29_WEIGHT = 58,
89+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_30_WEIGHT = 59,
90+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_31_WEIGHT = 60,
91+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_32_WEIGHT = 61,
92+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_33_WEIGHT = 62,
93+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_34_WEIGHT = 63,
94+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_35_WEIGHT = 64,
95+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_36_WEIGHT = 65,
96+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_37_WEIGHT = 66,
97+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_38_WEIGHT = 67,
98+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_39_WEIGHT = 68,
99+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_40_WEIGHT = 69,
100+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_41_WEIGHT = 70,
101+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_42_WEIGHT = 71,
102+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_43_WEIGHT = 72,
103+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_44_WEIGHT = 73,
104+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_45_WEIGHT = 74,
105+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_46_WEIGHT = 75,
106+
COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_47_WEIGHT = 76,
107+
COLOR_SETTING_SET_MAX_ANALOG_GAIN_CAP = 77,
108+
COLOR_SETTING_SET_MAX_DIGITAL_GAIN_CAP = 78,
109+
COLOR_SETTING_SET_FLICKER_FREE_FREQUENCY = 79,
110+
COLOR_SETTING_GET_EXPOSURE_MODE = 80,
111+
COLOR_SETTING_GET_WHITE_BALANCE_MODE = 81,
112+
COLOR_SETTING_SET_FRAME_RATE = 82,
113+
COLOR_SETTING_GET_FRAME_RATE = 83,
114+
};
115+
116+
} /* namespace libfreenect2 */
117+
118+
#endif /* COLOR_SETTINGS_H_ */

include/libfreenect2/libfreenect2.hpp

+40
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <libfreenect2/config.h>
3333
#include <libfreenect2/frame_listener.hpp>
3434
#include <libfreenect2/packet_pipeline.h>
35+
#include <libfreenect2/color_settings.h>
3536
#include <string>
3637
#include <vector>
3738

@@ -160,6 +161,45 @@ class LIBFREENECT2_API Freenect2Device
160161
/** Provide your listener to receive IR and depth frames. */
161162
virtual void setIrAndDepthFrameListener(FrameListener* ir_frame_listener) = 0;
162163

164+
/** Sets the RGB camera to fully automatic exposure setting.
165+
* Exposure compensation: negative value gives an underexposed image,
166+
* positive gives an overexposed image.
167+
*
168+
* @param exposure_compensation Exposure compensation, range [-2.0, 2.0]
169+
*/
170+
virtual void setColorAutoExposure(float exposure_compensation = 0) = 0;
171+
172+
/** Sets a flicker-free exposure time of the RGB camera in pseudo-ms, value in range [0.0, 640] ms.
173+
* The actual frame integration time is set to a multiple of fluorescent light period
174+
* that is shorter than the requested time e.g. requesting 16 ms will set 10 ms
175+
* in Australia (100Hz light flicker), 8.33 ms in USA (120Hz light flicker).
176+
* The gain is automatically set to compensate for the reduced integration time,
177+
* as if the gain was set to 1.0 and the integration time was the requested value.
178+
*
179+
* Requesting less than a single fluorescent light period will set the integration time
180+
* to the requested value, so the image brightness will flicker.
181+
*
182+
* To set the shortest non-flickering integration period for any country, simply set
183+
* a pseudo-exposure time of between (10.0, 16.667) ms, which will automatically drop
184+
* the integration time to 10 or 8.3 ms depending on country, while setting the analog
185+
* gain control to a brighter value.
186+
*
187+
* @param pseudo_exposure_time_ms Pseudo-exposure time in milliseconds, range (0.0, 66.0+]
188+
*/
189+
virtual void setColorSemiAutoExposure(float pseudo_exposure_time_ms) = 0;
190+
191+
/** Manually set true exposure time and analog gain of the RGB camera.
192+
* @param integration_time_ms True shutter time in milliseconds, range (0.0, 66.0]
193+
* @param analog_gain Analog gain, range [1.0, 4.0]
194+
*/
195+
virtual void setColorManualExposure(float integration_time_ms, float analog_gain) = 0;
196+
197+
/** Set/get an individual setting value of the RGB camera. */
198+
virtual void setColorSetting(ColorSettingCommandType cmd, uint32_t value) = 0;
199+
virtual void setColorSetting(ColorSettingCommandType cmd, float value) = 0;
200+
virtual uint32_t getColorSetting(ColorSettingCommandType cmd) = 0;
201+
virtual float getColorSettingFloat(ColorSettingCommandType cmd) = 0;
202+
163203
/** Start data processing with both RGB and depth streams.
164204
* All above configuration must only be called before start() or after stop().
165205
*

src/libfreenect2.cpp

+74
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <limits>
3434
#include <cmath>
3535
#include <cstdlib>
36+
#include <cstring>
3637
#include <fstream>
3738

3839
#define WRITE_LIBUSB_ERROR(__RESULT) libusb_error_name(__RESULT) << " " << libusb_strerror((libusb_error)__RESULT)
@@ -255,6 +256,13 @@ class Freenect2DeviceImpl : public Freenect2Device
255256

256257
virtual void setColorFrameListener(libfreenect2::FrameListener* rgb_frame_listener);
257258
virtual void setIrAndDepthFrameListener(libfreenect2::FrameListener* ir_frame_listener);
259+
virtual void setColorAutoExposure(float exposure_compensation = 0);
260+
virtual void setColorSemiAutoExposure(float pseudo_exposure_time_ms);
261+
virtual void setColorManualExposure(float integration_time_ms, float analog_gain);
262+
virtual void setColorSetting(ColorSettingCommandType cmd, uint32_t value);
263+
virtual void setColorSetting(ColorSettingCommandType cmd, float value);
264+
virtual uint32_t getColorSetting(ColorSettingCommandType cmd);
265+
virtual float getColorSettingFloat(ColorSettingCommandType cmd);
258266
virtual bool start();
259267
virtual bool startStreams(bool rgb, bool depth);
260268
virtual bool stop();
@@ -279,6 +287,14 @@ class Freenect2ReplayDevice : public Freenect2Device
279287
virtual void setColorFrameListener(FrameListener* listener);
280288
virtual void setIrAndDepthFrameListener(FrameListener* listener);
281289

290+
virtual void setColorAutoExposure(float exposure_compensation) {}
291+
virtual void setColorSemiAutoExposure(float pseudo_exposure_time_ms) {}
292+
virtual void setColorManualExposure(float integration_time_ms, float analog_gain) {}
293+
virtual void setColorSetting(ColorSettingCommandType cmd, uint32_t value) {}
294+
virtual void setColorSetting(ColorSettingCommandType cmd, float value) {}
295+
virtual uint32_t getColorSetting(ColorSettingCommandType cmd) { return 0u; }
296+
virtual float getColorSettingFloat(ColorSettingCommandType cmd) { return 0.0f; }
297+
282298
bool open();
283299

284300
virtual bool start();
@@ -736,6 +752,64 @@ void Freenect2DeviceImpl::setIrAndDepthFrameListener(libfreenect2::FrameListener
736752
pipeline_->getDepthPacketProcessor()->setFrameListener(ir_frame_listener);
737753
}
738754

755+
void Freenect2DeviceImpl::setColorAutoExposure(float exposure_compensation)
756+
{
757+
CommandTransaction::Result result;
758+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ACS, 0u), result);
759+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_MODE, 0u), result); // 0 == Fully auto
760+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_COMPENSATION, exposure_compensation), result);
761+
}
762+
763+
void Freenect2DeviceImpl::setColorSemiAutoExposure(float pseudo_exposure_time_ms)
764+
{
765+
CommandTransaction::Result result;
766+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ACS, 0u), result);
767+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_MODE, 3u), result); // 3 == Semi-auto
768+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_TIME_MS, pseudo_exposure_time_ms), result);
769+
}
770+
771+
void Freenect2DeviceImpl::setColorManualExposure(float integration_time_ms, float analog_gain)
772+
{
773+
CommandTransaction::Result result;
774+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ACS, 0u), result);
775+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_MODE, 4u), result); // 4 == Fully manual
776+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_INTEGRATION_TIME, integration_time_ms), result);
777+
command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ANALOG_GAIN, analog_gain), result);
778+
}
779+
780+
void Freenect2DeviceImpl::setColorSetting(ColorSettingCommandType cmd, uint32_t value)
781+
{
782+
CommandTransaction::Result result;
783+
command_tx_.execute(ColorSettingCommand(cmd, value), result);
784+
}
785+
786+
void Freenect2DeviceImpl::setColorSetting(ColorSettingCommandType cmd, float value)
787+
{
788+
CommandTransaction::Result result;
789+
command_tx_.execute(ColorSettingCommand(cmd, value), result);
790+
}
791+
792+
uint32_t Freenect2DeviceImpl::getColorSetting(ColorSettingCommandType cmd)
793+
{
794+
CommandTransaction::Result result;
795+
command_tx_.execute(ColorSettingCommand(cmd), result);
796+
if (result.size() < sizeof(ColorSettingResponse))
797+
{
798+
LOG_WARNING << "failed to get color setting, response size " << result.size() << " too small, expected " << sizeof(ColorSettingResponse);
799+
return 0u;
800+
}
801+
ColorSettingResponse const* data = reinterpret_cast<ColorSettingResponse const*>(&result[0]);
802+
return data->Data;
803+
}
804+
805+
float Freenect2DeviceImpl::getColorSettingFloat(ColorSettingCommandType cmd)
806+
{
807+
uint32_t data = getColorSetting(cmd);
808+
float out;
809+
memcpy(&out, &data, sizeof(out));
810+
return out;
811+
}
812+
739813
bool Freenect2DeviceImpl::open()
740814
{
741815
LOG_INFO << "opening...";

0 commit comments

Comments
 (0)