@@ -42,6 +42,8 @@ std::mutex g_mutex;
42
42
43
43
// / \brief WideAngle buffer
44
44
unsigned char *g_buffer = nullptr ;
45
+ unsigned char *g_bufferL8 = nullptr ;
46
+ unsigned char *g_bufferL16 = nullptr ;
45
47
46
48
// / \brief counter of received wideAngle msgs
47
49
int g_counter = 0 ;
@@ -68,6 +70,41 @@ void OnNewWideAngleFrame(const unsigned char *_data,
68
70
g_mutex.unlock ();
69
71
}
70
72
73
+ // ////////////////////////////////////////////////
74
+ // / \brief callback to get the wide angle camera image data
75
+ void OnNewWideAngleFrameMono (const unsigned char *_data,
76
+ unsigned int _width, unsigned int _height,
77
+ unsigned int _channels,
78
+ const std::string &_format)
79
+ {
80
+ g_mutex.lock ();
81
+
82
+ unsigned int bytesPerChannel = 0u ;
83
+ unsigned int bufferSize = 0u ;
84
+ if (_format == " L8" )
85
+ {
86
+ bytesPerChannel = 1u ;
87
+ bufferSize = _width * _height * _channels * bytesPerChannel;
88
+ if (!g_bufferL8)
89
+ g_bufferL8 = new unsigned char [bufferSize];
90
+ memcpy (g_bufferL8, _data, bufferSize);
91
+ }
92
+ else if (_format == " L16" )
93
+ {
94
+ bytesPerChannel = 2u ;
95
+ bufferSize = _width * _height * _channels * bytesPerChannel;
96
+ if (!g_bufferL16)
97
+ g_bufferL16 = new unsigned char [bufferSize];
98
+ memcpy (g_bufferL16, _data, bufferSize);
99
+ }
100
+
101
+ ASSERT_NE (0u , bytesPerChannel);
102
+ ASSERT_NE (0u , bufferSize);
103
+
104
+ g_counter++;
105
+ g_mutex.unlock ();
106
+ }
107
+
71
108
// ////////////////////////////////////////////////
72
109
TEST_F (WideAngleCameraTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(WideAngleCamera))
73
110
{
@@ -339,6 +376,8 @@ TEST_F(WideAngleCameraTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(WideAngleCamera))
339
376
EXPECT_EQ (bSumQ[1 ][0 ], bSumQ[0 ][1 ]);
340
377
341
378
// Clean up
379
+ delete [] g_buffer;
380
+ g_buffer = nullptr ;
342
381
engine->DestroyScene (scene);
343
382
}
344
383
@@ -460,3 +499,110 @@ TEST_F(WideAngleCameraTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Projection))
460
499
461
500
ASSERT_EQ (1u , camera.use_count ());
462
501
}
502
+
503
+ // ////////////////////////////////////////////////
504
+ TEST_F (WideAngleCameraTest,
505
+ GZ_UTILS_TEST_DISABLED_ON_WIN32 (WideAngleCameraMono))
506
+ {
507
+ CHECK_UNSUPPORTED_ENGINE (" optix" );
508
+
509
+ gz::rendering::ScenePtr scene = engine->CreateScene (" scene" );
510
+ ASSERT_NE (nullptr , scene);
511
+ scene->SetAmbientLight (1.0 , 1.0 , 1.0 );
512
+ scene->SetBackgroundColor (0.2 , 0.2 , 0.2 );
513
+
514
+ rendering::VisualPtr root = scene->RootVisual ();
515
+
516
+ unsigned int width = 20u ;
517
+ unsigned int height = 20u ;
518
+
519
+ // Create Wide Angle camera
520
+ auto cameraL8 = scene->CreateWideAngleCamera (" WideAngleCameraL8" );
521
+ ASSERT_NE (cameraL8, nullptr );
522
+ cameraL8->SetImageFormat (PF_L8);
523
+
524
+ auto cameraL16 = scene->CreateWideAngleCamera (" WideAngleCameraL16" );
525
+ ASSERT_NE (cameraL16, nullptr );
526
+ cameraL16->SetImageFormat (PF_L16);
527
+
528
+ CameraLens lens;
529
+ lens.SetCustomMappingFunction (1.05 , 4.0 , AFT_TAN, 1.0 , 0.0 );
530
+ lens.SetType (MFT_CUSTOM);
531
+ lens.SetCutOffAngle (GZ_PI);
532
+
533
+ cameraL8->SetLens (lens);
534
+ cameraL8->SetHFOV (2.6 );
535
+ cameraL8->SetImageWidth (width);
536
+ cameraL8->SetImageHeight (height);
537
+ scene->RootVisual ()->AddChild (cameraL8);
538
+
539
+ cameraL16->SetLens (lens);
540
+ cameraL16->SetHFOV (2.6 );
541
+ cameraL16->SetImageWidth (width);
542
+ cameraL16->SetImageHeight (height);
543
+ scene->RootVisual ()->AddChild (cameraL16);
544
+
545
+ // create blue material
546
+ MaterialPtr blue = scene->CreateMaterial ();
547
+ blue->SetAmbient (0.0 , 0.0 , 0.3 );
548
+ blue->SetDiffuse (0.0 , 0.0 , 0.8 );
549
+ blue->SetSpecular (0.5 , 0.5 , 0.5 );
550
+
551
+ // create box visual in front of cameras
552
+ VisualPtr box = scene->CreateVisual ();
553
+ box->AddGeometry (scene->CreateBox ());
554
+ box->SetOrigin (0.0 , 0.0 , 0.0 );
555
+ box->SetLocalPosition (2 , 0 , 0 );
556
+ box->SetLocalScale (1 , 1 , 1 );
557
+ box->SetMaterial (blue);
558
+ root->AddChild (box);
559
+
560
+ // Set a callback on the camera sensor to get a wide angle camera frame
561
+ gz::common::ConnectionPtr connection =
562
+ cameraL8->ConnectNewWideAngleFrame (
563
+ std::bind (OnNewWideAngleFrameMono,
564
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
565
+ std::placeholders::_4, std::placeholders::_5));
566
+ ASSERT_NE (nullptr , connection);
567
+ gz::common::ConnectionPtr connection2 =
568
+ cameraL16->ConnectNewWideAngleFrame (
569
+ std::bind (OnNewWideAngleFrameMono,
570
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
571
+ std::placeholders::_4, std::placeholders::_5));
572
+ ASSERT_NE (nullptr , connection2);
573
+
574
+ g_counter = 0 ;
575
+
576
+ // Update and verify
577
+ cameraL8->Update ();
578
+ EXPECT_EQ (1 , g_counter);
579
+
580
+ cameraL16->Update ();
581
+ EXPECT_EQ (2 , g_counter);
582
+
583
+ // Verify image format
584
+ EXPECT_EQ (PF_L8, cameraL8->ImageFormat ());
585
+ EXPECT_EQ (PF_L16, cameraL16->ImageFormat ());
586
+
587
+ // verify cameras can see the box in the middle and the pixel color value
588
+ // should be darker than the background (pixel at top center of image)
589
+ const unsigned int step = width;
590
+ unsigned int topMid = static_cast <unsigned int >(
591
+ step / 2.0 );
592
+ unsigned int mid = static_cast <unsigned int >(
593
+ height / 2.0 * step + step / 2.0 );
594
+ unsigned int topMidValue8 = g_bufferL8[topMid];
595
+ uint16_t topMidValue16 = reinterpret_cast <uint16_t *>(g_bufferL16)[topMid];
596
+ unsigned int midValue8 = g_bufferL8[mid];
597
+ uint16_t midValue16 = reinterpret_cast <uint16_t *>(g_bufferL16)[mid];
598
+
599
+ EXPECT_GT (topMidValue8, midValue8);
600
+ EXPECT_GT (topMidValue16, midValue16);
601
+
602
+ // Clean up
603
+ delete [] g_bufferL8;
604
+ g_bufferL8 = nullptr ;
605
+ delete [] g_bufferL16;
606
+ g_bufferL16 = nullptr ;
607
+ engine->DestroyScene (scene);
608
+ }
0 commit comments