I am trying to implement the Vector Field Histogram as described by Borenstein, Koren, 1991 in Python 2.7 using the SciPy stack.
I have already been able to calculate the polar histogram, as described in the paper, as well as the smoothing function to eliminate noise. This variable is stored in a numpy array, named self.Hist
.
However, the function computeTheta
, pasted below, which computes the steering direction, is only able to compute the proper direction if the valleys (i.e. consecutive sectors in the polar histogram whose obstacle density is below a certain threshold) do not contain the section where a full circle is completed, i.e. the sector corresponding to 360º
.
To make things clearer, consider these two examples:
- If the histogram contains a peak in the angles between, say,
330º
and30º
, with the rest of the histogram being a valley, then the steering direction will be computed correctly. If, however, the peak is contained between, say,
30º
and60º
, then the valley will start at60º
, go all the way past360º
and end in30º
, and the steering direction will be computed incorrectly, since this single valley will be considered two valleys, one between0º
and30º
, and another between60º
and360º
.def computeTheta(self, goal):
thrs = 2. s_max = 18 #We start by calculating the sector corresponding to the direction of the target. target_sector = int((180./np.pi)*np.arctan2(goal[1] - self.VCP[1], goal[0] - self.VCP[0])) if target_sector < 0: target_sector += 360 target_sector /= 5 #Next, we assume there is no best sector. best_sector = -1 dist_best_and_target = abs(target_sector - best_sector) #Then, we find the sector within a valley that is closest to the target sector. for k in range(self.Hist.shape[0]): if self.Hist[k] < thrs and abs(target_sector - k) < dist_best_and_target: best_sector = k dist_best_and_target = abs(target_sector - k) #If the sector is still -1, we return it as an error. print (target_sector, best_sector) if best_sector == -1: return -1 #If not, we can proceed... elif best_sector > -1: #... by deciding whether the valley to which the best sector belongs is a "wide" or a "narrow" one. #Assume it's wide. type_of_valley = "Wide" #If we find a sector that contradicts our assumption, we change our minds. for sector in range(best_sector, best_sector + s_max + 1): if sector < self.Hist.shape[0]: if self.Hist[sector] > thrs: type_of_valley = "Narrow" #If it is indeed a wide valley, we return the angle corresponding to the sector (k_n + s_max)/2. if type_of_valley == "Wide": theta = 5*(best_sector + s_max)/2 return theta #Otherwise, we find the far border of the valley and return the angle corresponding to the mean value between the best sector and the far border. elif type_of_valley == "Narrow": for sector in range(best_sector, best_sector + s_max): if self.Hist[sector] < thrs: far_border = sector theta = 5*(best_sector + far_border)/2 return theta
How can I address this issue? Is there a way to treat the histogram as circular? Is there maybe a better way to write this function?
Thank you for your time.