@@ -138,15 +138,15 @@ cdef class CMap2D:
138
138
# self._thresh_occupied # TODO
139
139
# self.thresh_free
140
140
141
- def from_scan (self , scan , resolution = 0.05 , limits = None , inscribed_radius = None ):
141
+ def from_scan (self , scan , resolution = 0.05 , limits = None , inscribed_radius = None , legacy = True ):
142
142
""" Creating a map from a scan places the x y origin in the center of the grid,
143
143
and generates the occupancy field from the laser data.
144
144
limits are in lidar frame (meters) [[xmin, xmax], [ymin, ymax]]
145
145
"""
146
146
angles = np.arange(scan.angle_min,
147
147
scan.angle_max + scan.angle_increment,
148
- scan.angle_increment)[:len (scan.ranges)]
149
- ranges = np.array(scan.ranges)
148
+ scan.angle_increment, dtype = np.float32 )[:len (scan.ranges)]
149
+ ranges = np.array(scan.ranges, dtype = np.float32 )
150
150
if inscribed_radius is not None :
151
151
ranges[ranges < inscribed_radius] = np.inf
152
152
xy_hits = (ranges * np.array([np.cos(angles), np.sin(angles)])).T
@@ -165,12 +165,18 @@ cdef class CMap2D:
165
165
self .resolution_ = resolution
166
166
self ._thresh_occupied = 0.9
167
167
self .thresh_free = 0.1
168
- ij_hits = self .xy_to_ij(xy_hits, clip_if_outside = False )
169
- is_inside = self .is_inside_ij(ij_hits.astype(np.float32))
170
- ij_hits = ij_hits[np.where(is_inside)]
171
- occupancy = 0.05 * np.ones((width, height), dtype = np.float32)
172
- occupancy[tuple (ij_hits.T)] = 0.95
173
- self ._occupancy = occupancy
168
+ if legacy:
169
+ ij_hits = self .xy_to_ij(xy_hits, clip_if_outside = False )
170
+ is_inside = self .is_inside_ij(ij_hits.astype(np.float32))
171
+ ij_hits = ij_hits[np.where(is_inside)]
172
+ occupancy = 0.05 * np.ones((width, height), dtype = np.float32)
173
+ occupancy[tuple (ij_hits.T)] = 0.95
174
+ self ._occupancy = occupancy
175
+ else :
176
+ observer_ij = self .xy_to_ij(np.array([[0 , 0 ]]))[0 ]
177
+ occupancy = np.ones((width, height), dtype = np.float32) * 0.5
178
+ self .creverse_raytrace_lidar(np.array(observer_ij).astype(np.int64), angles, ranges, occupancy)
179
+ self ._occupancy = occupancy
174
180
# ij_laser_orig = (-self.origin / self.resolution_).astype(int)
175
181
# compiled_reverse_raytrace(ij_hits, ij_laser_orig, self.occupancy_) # TODO
176
182
@@ -1564,6 +1570,74 @@ cdef class CMap2D:
1564
1570
if r > max_r:
1565
1571
break
1566
1572
1573
+ @ cython.boundscheck (False )
1574
+ @ cython.wraparound (False )
1575
+ @ cython.nonecheck (False )
1576
+ @ cython.cdivision (True )
1577
+ cdef creverse_raytrace_lidar(self , np.int64_t[::1 ] observer_ij,
1578
+ np.float32_t[::1 ] angles, np.float32_t[::1 ] ranges,
1579
+ np.float32_t[:, ::1 ] result):
1580
+ cdef np.int64_t o_i = observer_ij[0 ]
1581
+ cdef np.int64_t o_j = observer_ij[1 ]
1582
+ cdef np.float32_t threshold = self ._thresh_occupied
1583
+ cdef np.int64_t shape0 = self .occupancy_shape0
1584
+ cdef np.int64_t shape1 = self .occupancy_shape1
1585
+ cdef np.float32_t i_inc_unit
1586
+ cdef np.float32_t j_inc_unit
1587
+ cdef np.float32_t i_abs_inc
1588
+ cdef np.float32_t j_abs_inc
1589
+ cdef np.float32_t raystretch
1590
+ cdef np.int64_t max_inc
1591
+ cdef np.int64_t max_i_inc
1592
+ cdef np.int64_t max_j_inc
1593
+ cdef np.float32_t i_inc
1594
+ cdef np.float32_t j_inc
1595
+ cdef np.float32_t n_i
1596
+ cdef np.float32_t n_j
1597
+ cdef np.int64_t in_i
1598
+ cdef np.int64_t in_j
1599
+ cdef np.float32_t occ
1600
+ cdef np.int64_t di
1601
+ cdef np.int64_t dj
1602
+ cdef np.float32_t r
1603
+ cdef np.float32_t max_r
1604
+ cdef np.uint8_t is_hit
1605
+ for i in range (len (angles)):
1606
+ angle = angles[i]
1607
+ max_r = ranges[i] / self .resolution_
1608
+ i_inc_unit = ccos(angle)
1609
+ j_inc_unit = csin(angle)
1610
+ # Stretch the ray so that every 1 unit in the ray direction lands on a cell in i or
1611
+ i_abs_inc = abs (i_inc_unit)
1612
+ j_abs_inc = abs (j_inc_unit)
1613
+ raystretch = 1. / i_abs_inc if i_abs_inc >= j_abs_inc else 1. / j_abs_inc
1614
+ i_inc = i_inc_unit * raystretch
1615
+ j_inc = j_inc_unit * raystretch
1616
+ # max amount of increments before crossing the grid border
1617
+ if i_inc == 0 :
1618
+ max_inc = < np.int64_t> ((shape1 - 1 - o_j) / j_inc) if j_inc >= 0 else < np.int64_t> (o_j / - j_inc)
1619
+ elif j_inc == 0 :
1620
+ max_inc = < np.int64_t> ((shape0 - 1 - o_i) / i_inc) if i_inc >= 0 else < np.int64_t> (o_i / - i_inc)
1621
+ else :
1622
+ max_i_inc = < np.int64_t> ((shape1 - 1 - o_j) / j_inc) if j_inc >= 0 else < np.int64_t> (o_j / - j_inc)
1623
+ max_j_inc = < np.int64_t> ((shape0 - 1 - o_i) / i_inc) if i_inc >= 0 else < np.int64_t> (o_i / - i_inc)
1624
+ max_inc = max_i_inc if max_i_inc <= max_j_inc else max_j_inc
1625
+ # Trace a ray
1626
+ n_i = o_i + 0
1627
+ n_j = o_j + 0
1628
+ for n in range (1 , max_inc- 1 ):
1629
+ n_i += i_inc
1630
+ n_j += j_inc
1631
+ in_i = < np.int64_t> n_i
1632
+ in_j = < np.int64_t> n_j
1633
+ di = ( in_i - o_i )
1634
+ dj = ( in_j - o_j )
1635
+ r = sqrt(di* di + dj* dj)
1636
+ result[in_i, in_j] = 0.
1637
+ if r >= max_r:
1638
+ result[in_i, in_j] = 1.
1639
+ break
1640
+
1567
1641
cdef craymarch(self , np.int64_t[::1 ] observer_ij, np.int64_t[::1 ] angles, np.float32_t[::1 ] ranges):
1568
1642
cdef np.int64_t o_i = observer_ij[0 ]
1569
1643
cdef np.int64_t o_j = observer_ij[1 ]
0 commit comments