You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
705 lines
25 KiB
705 lines
25 KiB
// License: Apache 2.0. See LICENSE file in root directory.
|
|
// Copyright(c) 2022 Intel Corporation. All Rights Reserved.
|
|
|
|
#include "unit-tests-common.h"
|
|
|
|
|
|
std::vector< profile >
|
|
configure_all_supported_streams( rs2::sensor & sensor, int width, int height, int fps )
|
|
{
|
|
std::vector<profile> all_profiles =
|
|
{
|
|
{ RS2_STREAM_DEPTH, RS2_FORMAT_Z16, width, height, 0, fps},
|
|
{ RS2_STREAM_COLOR, RS2_FORMAT_RGB8, width, height, 0, fps},
|
|
{ RS2_STREAM_INFRARED, RS2_FORMAT_Y8, width, height, 1, fps},
|
|
{ RS2_STREAM_INFRARED, RS2_FORMAT_Y8, width, height, 2, fps},
|
|
{ RS2_STREAM_INFRARED, RS2_FORMAT_Y8, width, height, 0, fps},
|
|
{ RS2_STREAM_CONFIDENCE,RS2_FORMAT_RAW8, width, height, 0, fps},
|
|
{ RS2_STREAM_FISHEYE, RS2_FORMAT_RAW8, width, height, 0, fps},
|
|
{ RS2_STREAM_ACCEL, RS2_FORMAT_MOTION_XYZ32F, 1, 1, 0, 200},
|
|
{ RS2_STREAM_GYRO, RS2_FORMAT_MOTION_XYZ32F, 1, 1, 0, 200},
|
|
};
|
|
|
|
std::vector< profile > profiles;
|
|
std::vector< rs2::stream_profile > modes;
|
|
auto all_modes = sensor.get_stream_profiles();
|
|
|
|
for( auto profile : all_profiles )
|
|
{
|
|
if( std::find_if( all_modes.begin(),
|
|
all_modes.end(),
|
|
[&]( rs2::stream_profile p ) {
|
|
if( auto video = p.as< rs2::video_stream_profile >() )
|
|
{
|
|
if( p.fps() == profile.fps && p.stream_index() == profile.index
|
|
&& p.stream_type() == profile.stream && p.format() == profile.format
|
|
&& video.width() == profile.width && video.height() == profile.height )
|
|
{
|
|
modes.push_back( p );
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( auto motion = p.as< rs2::motion_stream_profile >() )
|
|
{
|
|
if( ( ( profile.fps / ( p.fps() + 1 ) ) <= 2.f )
|
|
&& // Approximate IMU rates. No need for being exact
|
|
p.stream_index() == profile.index && p.stream_type() == profile.stream
|
|
&& p.format() == profile.format )
|
|
{
|
|
modes.push_back( p );
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
} )
|
|
!= all_modes.end() )
|
|
{
|
|
profiles.push_back( profile );
|
|
}
|
|
}
|
|
if( modes.size() > 0 )
|
|
REQUIRE_NOTHROW( sensor.open( modes ) );
|
|
return profiles;
|
|
}
|
|
|
|
|
|
std::pair< std::vector< rs2::sensor >, std::vector< profile > >
|
|
configure_all_supported_streams( rs2::device & dev, int width, int height, int fps )
|
|
{
|
|
std::vector< profile > profiles;
|
|
std::vector< rs2::sensor > sensors;
|
|
auto sens = dev.query_sensors();
|
|
for( auto s : sens )
|
|
{
|
|
auto res = configure_all_supported_streams( s, width, height, fps );
|
|
profiles.insert( profiles.end(), res.begin(), res.end() );
|
|
if( res.size() > 0 )
|
|
{
|
|
sensors.push_back( s );
|
|
}
|
|
}
|
|
|
|
return { sensors, profiles };
|
|
}
|
|
|
|
|
|
std::string space_to_underscore( const std::string & text )
|
|
{
|
|
const std::string from = " ";
|
|
const std::string to = "__";
|
|
auto temp = text;
|
|
size_t start_pos = 0;
|
|
while( ( start_pos = temp.find( from, start_pos ) ) != std::string::npos )
|
|
{
|
|
temp.replace( start_pos, from.size(), to );
|
|
start_pos += to.size();
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
|
|
//inline long long current_time()
|
|
//{
|
|
// return (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 10000);
|
|
//}
|
|
|
|
//// disable in one place options that are sensitive to frame content
|
|
//// this is done to make sure unit-tests are deterministic
|
|
void disable_sensitive_options_for( rs2::sensor & sen )
|
|
{
|
|
if( sen.supports( RS2_OPTION_ERROR_POLLING_ENABLED ) )
|
|
REQUIRE_NOTHROW( sen.set_option( RS2_OPTION_ERROR_POLLING_ENABLED, 0 ) );
|
|
|
|
if( sen.supports( RS2_OPTION_ENABLE_AUTO_EXPOSURE ) )
|
|
REQUIRE_NOTHROW( sen.set_option( RS2_OPTION_ENABLE_AUTO_EXPOSURE, 0 ) );
|
|
|
|
if( sen.supports( RS2_OPTION_GLOBAL_TIME_ENABLED ) )
|
|
REQUIRE_NOTHROW( sen.set_option( RS2_OPTION_GLOBAL_TIME_ENABLED, 0 ) );
|
|
|
|
if( sen.supports( RS2_OPTION_EXPOSURE ) )
|
|
{
|
|
rs2::option_range range;
|
|
REQUIRE_NOTHROW(
|
|
range = sen.get_option_range( RS2_OPTION_EXPOSURE ) ); // TODO: fails sometimes with "Element Not Found!"
|
|
// float val = (range.min + (range.def-range.min)/10.f); // TODO - generate new records using the modified
|
|
// exposure
|
|
|
|
REQUIRE_NOTHROW( sen.set_option( RS2_OPTION_EXPOSURE, range.def ) );
|
|
}
|
|
}
|
|
|
|
|
|
void disable_sensitive_options_for( rs2::device & dev )
|
|
{
|
|
for( auto && s : dev.query_sensors() )
|
|
disable_sensitive_options_for( s );
|
|
}
|
|
|
|
|
|
bool wait_for_reset( std::function< bool( void ) > func, std::shared_ptr< rs2::device > dev )
|
|
{
|
|
if( func() )
|
|
return true;
|
|
|
|
WARN( "Reset workaround" );
|
|
|
|
try
|
|
{
|
|
dev->hardware_reset();
|
|
}
|
|
catch( ... )
|
|
{
|
|
}
|
|
return func();
|
|
}
|
|
|
|
|
|
bool is_usb3( const rs2::device & dev )
|
|
{
|
|
bool usb3_device = true;
|
|
try
|
|
{
|
|
std::string usb_type( dev.get_info( RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR ) );
|
|
// Device types "3.x" and also "" (for legacy playback records) will be recognized as USB3
|
|
usb3_device = ( std::string::npos == usb_type.find( "2." ) );
|
|
}
|
|
catch( ... ) // In case the feature not provided assume USB3 device
|
|
{
|
|
}
|
|
|
|
return usb3_device;
|
|
}
|
|
|
|
|
|
dev_type get_PID( rs2::device & dev )
|
|
{
|
|
dev_type designator{ "", true };
|
|
std::string usb_type{};
|
|
bool usb_descriptor = false;
|
|
|
|
REQUIRE_NOTHROW( designator.first = dev.get_info( RS2_CAMERA_INFO_PRODUCT_ID ) );
|
|
REQUIRE_NOTHROW( usb_descriptor = dev.supports( RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR ) );
|
|
if( usb_descriptor )
|
|
{
|
|
REQUIRE_NOTHROW( usb_type = dev.get_info( RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR ) );
|
|
designator.second = ( std::string::npos == usb_type.find( "2." ) );
|
|
}
|
|
|
|
return designator;
|
|
}
|
|
|
|
|
|
void command_line_params::init( int argc, char const * const * const argv )
|
|
{
|
|
rs2::log_to_file( RS2_LOG_SEVERITY_DEBUG );
|
|
}
|
|
|
|
|
|
static bool g_found_any_section = false;
|
|
|
|
|
|
bool found_any_section()
|
|
{
|
|
return g_found_any_section;
|
|
}
|
|
|
|
|
|
rs2::context make_context( const char * /*id*/ )
|
|
{
|
|
rs2::context ctx( rs2::context::uninitialized );
|
|
try
|
|
{
|
|
ctx = rs2::context( "{\"dds\":false}" );
|
|
g_found_any_section = true;
|
|
}
|
|
catch( ... )
|
|
{
|
|
std::cerr << "UNKNOWN EXCEPTiON in make_context!" << std::endl;
|
|
}
|
|
return ctx;
|
|
}
|
|
|
|
|
|
// Require that matrix is an orthonormal 3x3 matrix
|
|
void require_rotation_matrix(const float(&matrix)[9])
|
|
{
|
|
const float row0[] = { matrix[0], matrix[3], matrix[6] };
|
|
const float row1[] = { matrix[1], matrix[4], matrix[7] };
|
|
const float row2[] = { matrix[2], matrix[5], matrix[8] };
|
|
CAPTURE( full_precision( row0[0] ));
|
|
CAPTURE( full_precision( row0[1] ));
|
|
CAPTURE( full_precision( row0[2] ));
|
|
CAPTURE( full_precision( row1[0] ));
|
|
CAPTURE( full_precision( row1[1] ));
|
|
CAPTURE( full_precision( row1[2] ));
|
|
CAPTURE( full_precision( row2[0] ));
|
|
CAPTURE( full_precision( row2[1] ));
|
|
CAPTURE( full_precision( row2[2] ));
|
|
CHECK(dot_product(row0, row0) == approx(1.f));
|
|
CAPTURE( full_precision( dot_product( row1, row1 )));
|
|
CHECK( dot_product( row1, row1 ) == approx( 1.f ) ); // this line is problematic, and needs higher epsilon!!
|
|
CHECK_THAT(dot_product(row1, row1), approx_equals(1.f));
|
|
CHECK(dot_product(row2, row2) == approx(1.f));
|
|
CHECK(dot_product(row0, row1) == approx(0.f));
|
|
CHECK(dot_product(row1, row2) == approx(0.f));
|
|
CHECK(dot_product(row2, row0) == approx(0.f));
|
|
require_cross_product(row0, row1, row2);
|
|
require_cross_product(row0, row1, row2);
|
|
require_cross_product(row0, row1, row2);
|
|
}
|
|
|
|
// Require that matrix is exactly the identity matrix
|
|
void require_identity_matrix( const float ( &matrix )[9] )
|
|
{
|
|
static const float identity_matrix_3x3[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
|
|
for( int i = 0; i < 9; ++i )
|
|
REQUIRE( matrix[i] == approx( identity_matrix_3x3[i] ) );
|
|
}
|
|
|
|
//inline void test_wait_for_frames(rs2_device * device, std::initializer_list<stream_mode>& modes, std::map<rs2_stream, test_duration>& duration_per_stream)
|
|
//{
|
|
// rs2_start_device(device, require_no_error());
|
|
// REQUIRE( rs2_is_device_streaming(device, require_no_error()) == 1 );
|
|
//
|
|
// rs2_wait_for_frames(device, require_no_error());
|
|
//
|
|
// int lowest_fps_mode = std::numeric_limits<int>::max();
|
|
// for(auto & mode : modes)
|
|
// {
|
|
// REQUIRE( rs2_is_stream_enabled(device, mode.stream, require_no_error()) == 1 );
|
|
// REQUIRE( rs2_get_frame_data(device, mode.stream, require_no_error()) != nullptr );
|
|
// REQUIRE( rs2_get_frame_timestamp(device, mode.stream, require_no_error()) >= 0 );
|
|
// if (mode.framerate < lowest_fps_mode) lowest_fps_mode = mode.framerate;
|
|
// }
|
|
//
|
|
// std::vector<unsigned long long> last_frame_number;
|
|
// std::vector<unsigned long long> number_of_frames;
|
|
// last_frame_number.resize(RS2_STREAM_COUNT);
|
|
// number_of_frames.resize(RS2_STREAM_COUNT);
|
|
//
|
|
// for (auto& elem : modes)
|
|
// {
|
|
// number_of_frames[elem.stream] = 0;
|
|
// last_frame_number[elem.stream] = 0;
|
|
// }
|
|
//
|
|
// const auto actual_frames_to_receive = std::min(max_frames_to_receive, (uint32_t)(max_capture_time_sec* lowest_fps_mode));
|
|
// const auto first_frame_to_capture = (actual_frames_to_receive*0.1); // Skip the first 10% of frames
|
|
// const auto frames_to_capture = (actual_frames_to_receive - first_frame_to_capture);
|
|
//
|
|
// for (auto i = 0u; i< actual_frames_to_receive; ++i)
|
|
// {
|
|
// rs2_wait_for_frames(device, require_no_error());
|
|
//
|
|
// if (i < first_frame_to_capture) continue; // Skip some frames at the beginning to stabilize the stream output
|
|
//
|
|
// for (auto & mode : modes)
|
|
// {
|
|
// if (rs2_get_frame_timestamp(device, mode.stream, require_no_error()) > 0)
|
|
// {
|
|
// REQUIRE( rs2_is_stream_enabled(device, mode.stream, require_no_error()) == 1);
|
|
// REQUIRE( rs2_get_frame_data(device, mode.stream, require_no_error()) != nullptr);
|
|
// REQUIRE( rs2_get_frame_timestamp(device, mode.stream, require_no_error()) >= 0);
|
|
//
|
|
// auto frame_number = rs2_get_frame_number(device, mode.stream, require_no_error());
|
|
// if (!duration_per_stream[mode.stream].is_end_time_initialized && last_frame_number[mode.stream] != frame_number)
|
|
// {
|
|
// last_frame_number[mode.stream] = frame_number;
|
|
// ++number_of_frames[mode.stream];
|
|
// }
|
|
//
|
|
// if (!duration_per_stream[mode.stream].is_start_time_initialized && number_of_frames[mode.stream] >= 1)
|
|
// {
|
|
// duration_per_stream[mode.stream].start_time = std::chrono::high_resolution_clock::now();
|
|
// duration_per_stream[mode.stream].is_start_time_initialized = true;
|
|
// }
|
|
//
|
|
// if (!duration_per_stream[mode.stream].is_end_time_initialized && (number_of_frames[mode.stream] > (0.9 * frames_to_capture))) // Requires additional work for streams with different fps
|
|
// {
|
|
// duration_per_stream[mode.stream].end_time = std::chrono::high_resolution_clock::now();
|
|
// auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(duration_per_stream[mode.stream].end_time - duration_per_stream[mode.stream].start_time).count();
|
|
// auto fps = ((double)number_of_frames[mode.stream] / duration) * 1000.;
|
|
// //check_fps(fps, mode.framerate); // requires additional work to configure UVC controls in order to achieve the required fps
|
|
// duration_per_stream[mode.stream].is_end_time_initialized = true;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// rs2_stop_device(device, require_no_error());
|
|
// REQUIRE( rs2_is_device_streaming(device, require_no_error()) == 0 );
|
|
//}
|
|
|
|
|
|
static std::mutex m;
|
|
static std::mutex cb_mtx;
|
|
static std::condition_variable cv;
|
|
static std::atomic<bool> stop_streaming;
|
|
static int done;
|
|
|
|
|
|
void frame_callback( rs2::device & dev, rs2::frame frame, void * user )
|
|
{
|
|
std::lock_guard< std::mutex > lock( cb_mtx );
|
|
|
|
if( stop_streaming || ( frame.get_timestamp() == 0 ) )
|
|
return;
|
|
|
|
auto data = (user_data *)user;
|
|
bool stop = true;
|
|
|
|
auto stream_type = frame.get_profile().stream_type();
|
|
|
|
for( auto & elem : data->number_of_frames_per_stream )
|
|
{
|
|
if( elem.second < data->duration_per_stream[stream_type].actual_frames_to_receive )
|
|
{
|
|
stop = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if( stop )
|
|
{
|
|
stop_streaming = true;
|
|
{
|
|
std::lock_guard< std::mutex > lk( m );
|
|
done = true;
|
|
}
|
|
cv.notify_one();
|
|
return;
|
|
}
|
|
|
|
if( data->duration_per_stream[stream_type].is_end_time_initialized )
|
|
return;
|
|
|
|
unsigned num_of_frames = 0;
|
|
num_of_frames = ( ++data->number_of_frames_per_stream[stream_type] );
|
|
|
|
if( num_of_frames >= data->duration_per_stream[stream_type].actual_frames_to_receive )
|
|
{
|
|
if( ! data->duration_per_stream[stream_type].is_end_time_initialized )
|
|
{
|
|
data->duration_per_stream[stream_type].end_time = std::chrono::high_resolution_clock::now();
|
|
data->duration_per_stream[stream_type].is_end_time_initialized = true;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if( ( num_of_frames == data->duration_per_stream[stream_type].first_frame_to_capture )
|
|
&& ( ! data->duration_per_stream[stream_type]
|
|
.is_start_time_initialized ) ) // Skip some frames at the beginning to stabilize the stream output
|
|
{
|
|
data->duration_per_stream[stream_type].start_time = std::chrono::high_resolution_clock::now();
|
|
data->duration_per_stream[stream_type].is_start_time_initialized = true;
|
|
}
|
|
|
|
REQUIRE( frame.get_data() != nullptr );
|
|
REQUIRE( frame.get_timestamp() >= 0 );
|
|
}
|
|
|
|
//inline void test_frame_callback(device &device, std::initializer_list<stream_profile>& modes, std::map<rs2_stream, test_duration>& duration_per_stream)
|
|
//{
|
|
// done = false;
|
|
// stop_streaming = false;
|
|
// user_data data;
|
|
// data.duration_per_stream = duration_per_stream;
|
|
//
|
|
// for(auto & mode : modes)
|
|
// {
|
|
// data.number_of_frames_per_stream[mode.stream] = 0;
|
|
// data.duration_per_stream[mode.stream].is_start_time_initialized = false;
|
|
// data.duration_per_stream[mode.stream].is_end_time_initialized = false;
|
|
// data.duration_per_stream[mode.stream].actual_frames_to_receive = std::min(max_frames_to_receive, (uint32_t)(max_capture_time_sec* mode.fps));
|
|
// data.duration_per_stream[mode.stream].first_frame_to_capture = (uint32_t)(data.duration_per_stream[mode.stream].actual_frames_to_receive*0.1); // Skip the first 10% of frames
|
|
// data.duration_per_stream[mode.stream].frames_to_capture = data.duration_per_stream[mode.stream].actual_frames_to_receive - data.duration_per_stream[mode.stream].first_frame_to_capture;
|
|
// // device doesn't know which subdevice is providing which stream. could loop over all subdevices? no, because subdevices don't expose this information
|
|
// REQUIRE( rs2_is_stream_enabled(device, mode.stream, require_no_error()) == 1 );
|
|
// rs2_start(device, mode.stream, frame_callback, &data, require_no_error());
|
|
// }
|
|
//
|
|
// rs2_start_device(device, require_no_error());
|
|
// REQUIRE( rs2_is_device_streaming(device, require_no_error()) == 1 );
|
|
//
|
|
// {
|
|
// std::unique_lock<std::mutex> lk(m);
|
|
// cv.wait(lk, [&]{return done;});
|
|
// lk.unlock();
|
|
// }
|
|
//
|
|
// rs2_stop_device(device, require_no_error());
|
|
// REQUIRE( rs2_is_device_streaming(device, require_no_error()) == 0 );
|
|
//
|
|
// for(auto & mode : modes)
|
|
// {
|
|
// auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(data.duration_per_stream[mode.stream].end_time - data.duration_per_stream[mode.stream].start_time).count();
|
|
// auto fps = ((float)data.number_of_frames_per_stream[mode.stream] / duration) * 1000.;
|
|
// //check_fps(fps, mode.framerate); / TODO is not suppuorted yet. See above message
|
|
// }
|
|
//}
|
|
|
|
//inline void motion_callback(rs2_device * , rs2_motion_data, void *)
|
|
//{
|
|
//}
|
|
//
|
|
//inline void timestamp_callback(rs2_device * , rs2_timestamp_data, void *)
|
|
//{
|
|
//}
|
|
//
|
|
//// Provide support for doing basic streaming tests on a set of specified modes
|
|
//inline void test_streaming(rs2_device * device, std::initializer_list<stream_profile> modes)
|
|
//{
|
|
// std::map<rs2_stream, test_duration> duration_per_stream;
|
|
// for(auto & mode : modes)
|
|
// {
|
|
// duration_per_stream.insert(std::pair<rs2_stream, test_duration>(mode.stream, test_duration()));
|
|
// rs2_enable_stream(device, mode.stream, mode.width, mode.height, mode.format, mode.framerate, require_no_error());
|
|
// REQUIRE( rs2_is_stream_enabled(device, mode.stream, require_no_error()) == 1 );
|
|
// }
|
|
//
|
|
// test_wait_for_frames(device, modes, duration_per_stream);
|
|
//
|
|
// test_frame_callback(device, modes, duration_per_stream);
|
|
//
|
|
// for(auto & mode : modes)
|
|
// {
|
|
// rs2_disable_stream(device, mode.stream, require_no_error());
|
|
// REQUIRE( rs2_is_stream_enabled(device, mode.stream, require_no_error()) == 0 );
|
|
// }
|
|
//}
|
|
|
|
void test_option( rs2::sensor & device,
|
|
rs2_option option,
|
|
std::initializer_list< int > good_values,
|
|
std::initializer_list< int > bad_values )
|
|
{
|
|
// Test reading the current value
|
|
float first_value;
|
|
REQUIRE_NOTHROW( first_value = device.get_option( option ) );
|
|
|
|
|
|
// check if first value is something sane (should be default?)
|
|
rs2::option_range range;
|
|
REQUIRE_NOTHROW( range = device.get_option_range( option ) );
|
|
REQUIRE( first_value >= range.min );
|
|
REQUIRE( first_value <= range.max );
|
|
CHECK( first_value == range.def );
|
|
|
|
// Test setting good values, and that each value set can be subsequently get
|
|
for( auto value : good_values )
|
|
{
|
|
REQUIRE_NOTHROW( device.set_option( option, (float)value ) );
|
|
REQUIRE( device.get_option( option ) == value );
|
|
}
|
|
|
|
// Test setting bad values, and verify that they do not change the value of the option
|
|
float last_good_value;
|
|
REQUIRE_NOTHROW( last_good_value = device.get_option( option ) );
|
|
for( auto value : bad_values )
|
|
{
|
|
REQUIRE_THROWS_AS( device.set_option( option, (float)value ), rs2::error );
|
|
REQUIRE( device.get_option( option ) == last_good_value );
|
|
}
|
|
|
|
// Test that we can reset the option to its original value
|
|
REQUIRE_NOTHROW( device.set_option( option, first_value ) );
|
|
REQUIRE( device.get_option( option ) == first_value );
|
|
}
|
|
|
|
|
|
rs2::stream_profile get_profile_by_resolution_type( rs2::sensor & s, res_type res )
|
|
{
|
|
auto sp = s.get_stream_profiles();
|
|
int width = 0, height = 0;
|
|
for( auto && p : sp )
|
|
{
|
|
if( auto video = p.as< rs2::video_stream_profile >() )
|
|
{
|
|
width = video.width();
|
|
height = video.height();
|
|
if( ( res = get_res_type( width, height ) ) )
|
|
return p;
|
|
}
|
|
}
|
|
std::stringstream ss;
|
|
ss << "stream profile for " << width << "," << height << " resolution is not supported!";
|
|
throw std::runtime_error( ss.str() );
|
|
}
|
|
|
|
|
|
std::shared_ptr< rs2::device > do_with_waiting_for_camera_connection( rs2::context ctx,
|
|
std::shared_ptr< rs2::device > dev,
|
|
std::string serial,
|
|
std::function< void() > operation )
|
|
{
|
|
std::mutex m;
|
|
bool disconnected = false;
|
|
bool connected = false;
|
|
std::shared_ptr< rs2::device > result;
|
|
std::condition_variable cv;
|
|
|
|
ctx.set_devices_changed_callback( [&]( rs2::event_information info ) mutable {
|
|
if( info.was_removed( *dev ) )
|
|
{
|
|
std::unique_lock< std::mutex > lock( m );
|
|
disconnected = true;
|
|
cv.notify_all();
|
|
}
|
|
auto list = info.get_new_devices();
|
|
if( list.size() > 0 )
|
|
{
|
|
for( auto cam : list )
|
|
{
|
|
if( serial == cam.get_info( RS2_CAMERA_INFO_SERIAL_NUMBER ) )
|
|
{
|
|
std::unique_lock< std::mutex > lock( m );
|
|
connected = true;
|
|
result = std::make_shared< rs2::device >( cam );
|
|
|
|
disable_sensitive_options_for( *result );
|
|
cv.notify_all();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
operation();
|
|
|
|
std::unique_lock< std::mutex > lock( m );
|
|
REQUIRE( wait_for_reset(
|
|
[&]() { return cv.wait_for( lock, std::chrono::seconds( 20 ), [&]() { return disconnected; } ); },
|
|
dev ) );
|
|
REQUIRE( cv.wait_for( lock, std::chrono::seconds( 20 ), [&]() { return connected; } ) );
|
|
REQUIRE( result );
|
|
ctx.set_devices_changed_callback( []( rs2::event_information info ) {} ); // reset callback
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
rs2::depth_sensor restart_first_device_and_return_depth_sensor( const rs2::context & ctx,
|
|
const rs2::device_list & devices_list )
|
|
{
|
|
rs2::device dev = devices_list[0];
|
|
std::string serial;
|
|
REQUIRE_NOTHROW( serial = dev.get_info( RS2_CAMERA_INFO_SERIAL_NUMBER ) );
|
|
// forcing hardware reset to simulate device disconnection
|
|
auto shared_dev = std::make_shared< rs2::device >( devices_list.front() );
|
|
shared_dev = do_with_waiting_for_camera_connection( ctx, shared_dev, serial, [&]() { shared_dev->hardware_reset(); } );
|
|
REQUIRE( shared_dev );
|
|
rs2::depth_sensor depth_sensor = shared_dev->query_sensors().front();
|
|
return depth_sensor;
|
|
}
|
|
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <wchar.h>
|
|
#include <KnownFolders.h>
|
|
#include <shlobj.h>
|
|
|
|
std::string get_folder_path( special_folder f )
|
|
{
|
|
std::string res;
|
|
if( f == temp_folder )
|
|
{
|
|
TCHAR buf[MAX_PATH];
|
|
if( GetTempPath( MAX_PATH, buf ) != 0 )
|
|
{
|
|
char str[1024];
|
|
wcstombs( str, buf, 1023 );
|
|
res = str;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GUID folder;
|
|
switch( f )
|
|
{
|
|
case user_desktop:
|
|
folder = FOLDERID_Desktop;
|
|
break;
|
|
case user_documents:
|
|
folder = FOLDERID_Documents;
|
|
break;
|
|
case user_pictures:
|
|
folder = FOLDERID_Pictures;
|
|
break;
|
|
case user_videos:
|
|
folder = FOLDERID_Videos;
|
|
break;
|
|
default:
|
|
throw std::invalid_argument( std::string( "Value of f (" ) + std::to_string( f )
|
|
+ std::string( ") is not supported" ) );
|
|
}
|
|
PWSTR folder_path = NULL;
|
|
HRESULT hr = SHGetKnownFolderPath( folder, KF_FLAG_DEFAULT_PATH, NULL, &folder_path );
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
char str[1024];
|
|
wcstombs( str, folder_path, 1023 );
|
|
CoTaskMemFree( folder_path );
|
|
res = str;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
#endif //_WIN32
|
|
|
|
#if defined __linux__ || defined __APPLE__
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <pwd.h>
|
|
|
|
std::string get_folder_path( special_folder f )
|
|
{
|
|
std::string res;
|
|
if( f == special_folder::temp_folder )
|
|
{
|
|
const char * tmp_dir = getenv( "TMPDIR" );
|
|
res = tmp_dir ? tmp_dir : "/tmp/";
|
|
}
|
|
else
|
|
{
|
|
const char * home_dir = getenv( "HOME" );
|
|
if( ! home_dir )
|
|
{
|
|
struct passwd * pw = getpwuid( getuid() );
|
|
home_dir = ( pw && pw->pw_dir ) ? pw->pw_dir : "";
|
|
}
|
|
if( home_dir )
|
|
{
|
|
res = home_dir;
|
|
switch( f )
|
|
{
|
|
case user_desktop:
|
|
res += "/Desktop/";
|
|
break;
|
|
case user_documents:
|
|
res += "/Documents/";
|
|
break;
|
|
case user_pictures:
|
|
res += "/Pictures/";
|
|
break;
|
|
case user_videos:
|
|
res += "/Videos/";
|
|
break;
|
|
default:
|
|
throw std::invalid_argument( std::string( "Value of f (" ) + std::to_string( f )
|
|
+ std::string( ") is not supported" ) );
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
#endif // defined __linux__ || defined __APPLE__
|