• Keine Ergebnisse gefunden

5.2 Motion Planner Implementation

5.2.2 Planner Implementation on the GPU

5.2.2.3 State Lattice Construction

As is mentioned earlier, the path edges are multiplied into several trajectory edges by associating acceleration profiles with them. Trajectory edges that arrive at the same lattice nodeN(is, il, iα, iv, it) are subject to a pruning operation. The speed and time of the end state of the trajectory edge that survives the pruning operation are selected to represent the lattice node. The traversal cost of the trajectory segment from the vehicle to this newly represented node is recorded in a cost map. Each cell of this map is indexed by (is, il, iα, iv, it) and corresponds to the lattice node in the state lattice indexed in the same way. Besides the traversal cost, the time and the speed, the information recorded in the cell also contains:

• The index of the parent node of the current node, i.e., the source node of the trajectory edge ec that ends at the current node.

• The coefficients, starting time, starting speed and duration of the last acceleration cubic polynomial along the current trajectory edge. Note thatthe last polynomial is stressed here because a trajectory edge might contain one or two acceleration cubic polynomials. Referring to Chapter4, if there happen to be two polynomials,

the first one is the remaining segment of the acceleration profile applied on the preceding trajectory edges. In this case, the information of the first polynomial must already be recorded at the preceding node. As a result, it is no longer neces-sary to record it again, unless it is still unfinished within the current edgeec. The information of the polynomial is necessary for the construction of the subsequent trajectory edges. Besides, it is also indispensable for the reconstruction of the best constraint-abiding trajectory after the state lattice construction is finished and the best target node is selected.

• The time index of the first sample on the remaining segment of the last profile on ec for which the dynamic cost will be evaluated on the subsequent edges. This is only useful when the profile is unfinished within the current trajectory edge. In this case, the dynamic cost evaluation of the subsequent trajectory edges will start at this sample.

• The sampling interval in terms of time of the last profile on ec for dynamic cost evaluation. It is calculated as

PROFILE-DURATION

PROFILE-ARC-LENGTH

PATH-SAMPLING-STEP + 1. (5.2)

When the profile is unfinished onec, its remaining part will be evaluated with the same sampling interval on the next edge.

• The curvature of the last sample on ec. This curvature, in combination with the curvature of the first sample on the following edge, is used to calculate the rate of change of curvature which is one subject for the dynamic cost evaluation.

• The arc length of the unfinished segment of the current acceleration profile. This is necessary for the construction of the subsequent trajectory edge.

• The desirability of the target node n1 of ec in terms of speed and time. The sum of this cost term and the traversal cost will be used for the pruning operation to select the best candidate for representing the state lattice node thatn1 coincides with. Shouldn1 survive the pruning, both the aggregate cost and the desirability cost will be stored at the corresponding cell of the cost map at the end of the current thread. At the beginning of the thread where the subsequent trajectories starting from n1 are constructed, the desirability cost will be subtracted from the aggregate cost, which results in the traversal cost of the trajectory from the vehicle start state to the current node. This traversal cost will be used for the cost evaluations of the subsequent edges.

The cost map is stored in several arrays. Each array records one piece of the infor-mation listed above. The array element corresponding to the grid cell (is, il, iα, iv, it) of the cost map is indexed by:

idxN =isnαnvntnl+iαnvntnl+ivntnl+itnl+il

where nα, nv, nt, nl refer to the number of acceleration profiles, the number of speed discretizations, the number of time discretizations and the number of latitude discretiza-tions in the SL frame. Recall that the state lattice may contain several sections. Ac-cordingly, the overall size of the state lattice is given as:

sumidx(nsec) =

nsec−1

X

isec=0

ns(isec)nαnvntnl(isec)

where nsec is the number of sections, ns(isec) and nl(isec) refer to the number of the station discretizations and the number of latitude discretizations in theSLframe of the ith section. In this way, the indices of the lattice nodes of one section begin with:

idxstart(isec) =

( 0 ifisec = 0 sumidx(isec) otherwise

These starting indices of the sections are also stored in an array to facilitate the calculation of the index of the lattice nodes in the cost map.

Figure5.8demonstrates how the threads for constructing the trajectory edges inter-act with the storage of the cost map and path edges. The construction of the trajectories is conducted in order of station. Each state lattice node initiates a thread executing the kernel which implements the algorithm demonstrated in Algorithm 1. In general, at most NcNα trajectory edges can be constructed in one thread which result in NcNα

candidate nodes. Note that Nc refers to the number of the path edges outgoing from one lattice node according to the definition of the connectivity pattern. It might be intuitive to make the kernel write the information of the candidate nodenc to the cor-responding memory of the to-be-represented node ns if the cost of nc turns out to be smaller than the cost of the current representative state ofns. Recall that there might be several threads executing the instructions of the kernel concurrently. Consequently, it might happen that some of the threads need to modify the same memory segment as the trajectories generated by them end at the same to-be-represented node. To avoid race conditions, the built-in atomic functionatomicMin() is employed to assign the smallest cost to the memory segment. atomicMin() ensures that the memory address can only be accessed by a second thread after the first thread completes its operation on this

memory address. If several candidate nodes turn out to have the same cost which hap-pens to be the smallest cost, it is defined that the one generated by the thread with the smallest thread index will win, as is shown by the second atomicMin() in Figure 5.8.

This strategy is just used for the purpose of convenience; there is no reason behind it (since the decision of the pruning selection is based solely on the cost, the candidate nodes with the same cost are supposed to be treated equally).

The implementation of the pruning process illustrated above works if all the threads that are initiated by the lattice nodes of a single station have strict step-wise syn-chronization. Otherwise, the construction of the state lattice will become crazy. For example, the thread that generates a candidate trajectory whose ending node does not have the minimum cost might be able to pass the tests of the two atomicMin() and writes the information of its ending node to corresponding memory, whereas the thread that has the minimum-cost candidate node might be kept back. As a result, it is neces-sary to check how the threads are synchronized in the computing architecture of CUDA.

It turns out that only the threads that belong to the same block ( cf. Figure 5.6 for the concepts of block and thread) are strictly synchronized on current CUDA-enabled GPUs. That is, the threads that belong to different blocks may not execute the same instruction at the same time. Consequently, the implementation of the selection of the best candidate node presented above should be modified. The common method used to realize a global synchronization is to invoke a kernel from the host, as it is regulated that only after all the threads executing the current kernel are finished can the new kernel be launched. Accordingly, it is common practice to split a kernel at the points where a global synchronization is required and launch the resultant sub-kernels sequentially.

The current execution of the kernel for constructing the trajectory edges and selecting the best candidate node adopts that “pipeline” method, as is shown in Figure5.9.

As can be seen in Figure5.8and Figure5.9, the storage schemes of the path edges and the lattice nodes can facilitate contiguous memory accesses among consecutive threads, which is helpful in maximizing the memory throughput of CUDA-based applications.

The algorithm for the application of the acceleration profiles presented in Section4.3 is implemented in the threads for the construction of the trajectory edges demonstrated in Figure 5.8. Recall that extra nodes will be generated to record the stopping states of the vehicle that occur somewhere between connected lattice nodes should there be any. Such extra nodes are called EXTRA-SAMPLEs (cf. Section 4.2). The indices iv and it of the cell of the cost map where the information of an EXTRA-SAMPLE is stored are zero and the maximum time index, respectively. Its indices is, il and iα are set in accord with the intended target node of the trajectory along which the EXTRA-SAMPLE in question occurs. In addition, the representative time value of the cell is set to ∞, communicating a message to the subsequent threads initiated by this particular cell that no further expansion should be carried out after it.

0 1 0 1 0 1 0 1

atomicMin(address(N0000.c), Ncandidate.cost)

atomicMin(address(AugmentedNodeArray[i]), ith)

size(AugmentedArray) = #(Ntarget)Nk

Figure 5.8: Static cost evaluation of path edges and the construction of the trajectories outgoing from a single station on the GPU.

Generation of trajectory edges

Figure 5.9: The kernel pipeline for constructing the trajectory edges and select-ing the best candidate node.