@@ -435,11 +435,62 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
435435 break ;
436436
437437 case mjSENS_RANGEFINDER : // rangefinder
438- rvec [0 ] = d -> site_xmat [9 * objid + 2 ];
439- rvec [1 ] = d -> site_xmat [9 * objid + 5 ];
440- rvec [2 ] = d -> site_xmat [9 * objid + 8 ];
441- d -> sensordata [adr ] = mj_ray (m , d , d -> site_xpos + 3 * objid , rvec , NULL , 1 ,
442- m -> site_bodyid [objid ], NULL );
438+ if (objtype == mjOBJ_SITE ) {
439+ rvec [0 ] = d -> site_xmat [9 * objid + 2 ];
440+ rvec [1 ] = d -> site_xmat [9 * objid + 5 ];
441+ rvec [2 ] = d -> site_xmat [9 * objid + 8 ];
442+ d -> sensordata [adr ] = mj_ray (m , d , d -> site_xpos + 3 * objid , rvec , NULL , 1 ,
443+ m -> site_bodyid [objid ], NULL );
444+ } else {
445+ // camera-attached rangefinder: depth image
446+ const int width = m -> cam_resolution [2 * objid ];
447+ const int height = m -> cam_resolution [2 * objid + 1 ];
448+ const int bodyexclude = m -> cam_bodyid [objid ];
449+ const mjtNum * cam_xpos = d -> cam_xpos + 3 * objid ;
450+ const mjtNum * cam_xmat = d -> cam_xmat + 9 * objid ;
451+ const int projection = m -> cam_projection [objid ];
452+
453+ // compute focal length in pixels using helper
454+ mjtNum fx , fy , cx , cy , ortho_extent ;
455+ mju_camIntrinsics (m , objid , & fx , & fy , & cx , & cy , & ortho_extent );
456+
457+ if (projection == mjPROJ_PERSPECTIVE ) {
458+ // perspective: all rays share origin, different directions
459+ const int npixel = width * height ;
460+ mj_markStack (d );
461+ mjtNum * vec = mjSTACKALLOC (d , 3 * npixel , mjtNum );
462+ int * geomid = mjSTACKALLOC (d , npixel , int );
463+
464+ // compute ray directions using helper (normalized)
465+ for (int row = 0 ; row < height ; row ++ ) {
466+ for (int col = 0 ; col < width ; col ++ ) {
467+ int idx = row * width + col ;
468+ mjtNum origin [3 ];
469+ mju_camPixelRay (origin , vec + 3 * idx , cam_xpos , cam_xmat ,
470+ col , row , fx , fy , cx , cy , projection , ortho_extent );
471+ }
472+ }
473+
474+ // cast all rays
475+ mj_multiRay (m , d , cam_xpos , vec , NULL , 1 , bodyexclude ,
476+ geomid , d -> sensordata + adr , npixel , mjMAXVAL );
477+
478+ mj_freeStack (d );
479+ } else {
480+ // orthographic: parallel rays, different origins
481+ for (int row = 0 ; row < height ; row ++ ) {
482+ for (int col = 0 ; col < width ; col ++ ) {
483+ int idx = row * width + col ;
484+ mjtNum origin [3 ], direction [3 ];
485+ mju_camPixelRay (origin , direction , cam_xpos , cam_xmat ,
486+ col , row , fx , fy , cx , cy , projection , ortho_extent );
487+
488+ d -> sensordata [adr + idx ] = mj_ray (m , d , origin , direction , NULL , 1 ,
489+ bodyexclude , NULL );
490+ }
491+ }
492+ }
493+ }
443494
444495 break ;
445496
0 commit comments