Giter Site home page Giter Site logo

fjp / frenet Goto Github PK

View Code? Open in Web Editor NEW
215.0 5.0 65.0 1.81 MB

Transform Frenet (s,d) to local Cartesian (x,y) coordinates.

Home Page: https://fjp.at/posts/optimal-frenet/

License: MIT License

MATLAB 3.75% Python 4.04% Jupyter Notebook 31.83% HTML 60.36% Shell 0.02%
trajectory frenet frenet-transformation vehicle path-planning pathfinding-algorithm

frenet's Introduction

Trajectory Planning in the Frenet Space

There are many ways to plan a trajectory for a robot. A trajectory can be seen as a set of time ordered state vectors $x$. The following algorithm introduces a way to plan trajectories to maneuver a mobile robot in a 2D plane. It is specifically useful for structured environments, like highways, where a rough path, referred to as reference, is available a priori.

Path planning in frenet coordinates:

Trajectory Planning using frenet coordinates.

Algorithm

  1. Determine the trajectory start state $[x_1,x_2,\theta,\kappa,v,a](0)$ The trajectory start state is obtained by evaluating the previously calculated trajectory at the prospective start state (low-level-stabilization). At system initialization and after reinitialization, the current vehicle position is used instead (high-level-stabilization).
  2. Selection of the lateral mode Depending on the velocity $v$ the time based ($d(t)$) or running length / arc length based ($d(s)$) lateral planning mode is activated. By projecting the start state onto the reference curve the the longitudinal start position $s(0)$ is determined. The frenet state vector $[s,\dot{s},\ddot{s},d,d',d''](0)$ can be determined using the frenet transformation. For the time based lateral planning mode, $[\dot{d}, \ddot{d}](0)$ need to be calculated.
  3. Generating the laterl and longitudinal trajectories Trajectories including their costs are generated for the lateral (mode dependent) as well as the longitudinal motion (velocity keeping, vehicle following / distance keeping) in the frenet space. In this stage, trajectories with high lateral accelerations with respect to the reference path can be neglected to improve the computational performance.
  4. Combining lateral and longitudinal trajectories Summing the partial costs of lateral and longitduinal costs using $J(d(t),s(t)) = J_d(d(t)) + k_s \cdot J_s(s(t))$, for all active longidtuinal mode every longitudinal trajectory is combined with every lateral trajectory and transfromed back to world coordinates using the reference path. The trajectories are verified if they obey physical driving limits by subsequent point wise evaluation of curvature and acceleration. This leads to a set of potentially drivable maneuvers of a specific mode in world coordinates.
  5. Static and dynamic collision check Every trajectory set is evaluated with increasing total costs if static and dynamic collisions are avoided. The trajectory with the lowest cost is then selected.
  6. Longitudinal mode alternation Using the sign based (in the beginning) jerk $\dot{a}(0)$, the trajectory with the strongest decceleration or the trajectory which accelerates the least respectively is selected and passed to the controller.

Frenet Coordinates

"Frenet Coordinates", are a way of representing position on a road in a more intuitive way than traditional (x,y) Cartesian Coordinates.

With Frenet coordinates, we use the variables s and d to describe a vehicle's position on the road or a reference path. The s coordinate represents distance along the road (also known as longitudinal displacement) and the d coordinate represents side-to-side position on the road (relative to the reference path), and is also known as lateral displacement.

In the following sections the advantages and disadvantages of Frenet coordinates are compared to the Cartesian coordinates.

Frenet Features

The image below depicts a curvy road with a Cartesian coordinate system laid on top of it, as well as a curved (continuously curved) reference path (for example the middle of the road).

Representation of a reference path (blue) in Cartesian coordinates (x,d).

The next image shows the same reference path together with its Frenet coordinates.

Representation of a reference path in Frenet coordinates (s,d) on a road segment.

The s coordinate represents the run length and starts with s = 0 at the beginning of the reference path. Lateral positions relative to the reference path are are represented with the d coordinate. Positions on the reference path are represented with d = 0. d is positive to the left of the reference path and negative on the right of it, although this depends on the convention used for the local reference frame.

The image above shows that curved reference paths (such as curvy roads) are represented as straight lines on the s axis in Frenet coordinates. However, motions that do not follow the reference path exactly result in non straight motions in Frenet coordinates. Instead such motions result in an offset from the reference path and therefore the s axis, which is described with the d coordinate. The following image shows the two different representations (Cartesian vs Frenet).

Comparison of a planned trajectory in Cartesian and Frenet coordinates.

To use Frenet coordinates it is required to have a continouosly smooth reference path.

Reference Path

Frenet coordinates provide a mathematically simpler representation of a reference path, because its run length is described with the s axis. This reference path provides a rough reference to follow an arbitrary but curvature continuous course of the road. To avoid collisions, the planner must take care of other objects in the environment, either static or dynamic. Such objects are usually not avoided by the reference path.

A reference path can be represented in two different forms although for all representations a run length information, which represents the s axis, is required for the transformation.

  • Polynome
  • Spline (multiple polynomes)
  • Clothoid (special polynome)
  • Polyline (single points with run length information)

Clothoid

$$ x(l) = c0 + c1*l $$

Polyline

Transformation

The transformation from local vehicle coordinates to Frenet coordinates is based on the relations shown in the following image:

Transformation vehicle frame to Frenet frame.

Given a point $P_C$ in the vehicle frame search for the closest point $R_C$ on the reference path. The run length of $R_C$, which is known from the reference path points, determins the s coordinate of the transformed point $P_F$. If the reference path is sufficiently smooth (continuously differentiable) then the vector $\vec{PR}$ is orthogonal to the reference path at the point $R_C$. The signed length of $\vec{PR}$ determines the d coordinate of $P_F$. The sign is positive, if $P_C$ lies on the left along the run lenght of the reference path.

The procedure to transform a point $P_F$ from Frenet coordinates to the local vehicle frame in Cartesian coordinates is analogous. First, the point $R_C$, which lies on the reference path at run length $s$. Next, a normal unit vector $\vec{d}$ is determined, which, in this point, is orthogonal to the reference path. The direction of this vector points towards positive $d$ values and therefore points to the left with increasing run length $s$. Therefore, the vector $\vec{d}$ depends on the run length, which leads to:

$$ P_C(s,d) = R_C(s) + d \cdot \vec{d}(s) $$

Usage

Jupyter Notebook

In the python folder you find a Jupyter Notebook which shows the described planning algorithm.

Frenet GUI

Note: The Frenet GUI is not functional yet. Contributions are welcome. Here's the plan for this GUI:

Allows you to generate trajectories in a local (world) reference frame from two quintic polynomials. One polynomial describes the longitudinal direction and the other one the lateral. Providing a reference path and applying the Frenet coordinate transformation on this path will result in a trajectory.

Execute frenet.sh run the GUI. This will call uic (Qt's user interface compiler) to process the ui file. Afterwards the main.py will be executed.

Dependencies

The GUI was created with python3 in a conda environment:

conda create -n frenetenv python=3.6
conda activate frenetenv
conda install -c conda-forge pyside2
conda install -c conda-forge matplotlib

You can use the provided environment.yml to create a conda environment with the required dependendies:

conda create --name <env-name> --file environment.yml
conda activate <env-name>

References

Python code:

Helper Function

https://de.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections

frenet's People

Contributors

fjp avatar kexianshen avatar matlabor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

frenet's Issues

wrong polynomial coefficients in cQuarticPoly.m

Some polynomial coefficients are wrong in cQuarticPoly.m.

It should be:

line 30: x = obj.c(2) + 2 * obj.c(3).*t + 3 * obj.c(4).*t.^2 + 4 * obj.c(5).*t.^3;

line 34: x = 2 * obj.c(3) + 6 * obj.c(4).*t + 12 * obj.c(5).*t.^2;

Frenet to Cartesian Coordinates

Hello,

I have some doubts in the FRT2Cart function in MATLAB.

    nNextRefPoint = 0;

    while ((i_fS > i_faRefRunLength(nNextRefPoint+1)) && (nNextRefPoint < length(i_faRefRunLength)))

        nNextRefPoint = nNextRefPoint + 1;
    end

    nPrevRefPoint = nNextRefPoint-1;

Can you please explain me what these variables mean? And what exactly is happening here?

Difference in Cart2FRT and FRT2Cart in transformation.m

Hi Franz,

I would first like to thank you for building such a repo. I was trying out the transformation.m file. At the end of the code, we compare transform from Cartesian to Frenet and back to Cartesian. The results are not the same and we have some error in both the x and y positions. I thought this could be due to the ds=0.1. However, reducing ds by orders of magnitude did not help much in reducing the error. Is there any specific reason for this or is there a bug in the code that we need to look for?

Thanks,
Iman

There is an error about Qt when running

python main.py 
['/home/ugv-yu/bryan/Frenet/frenet/python', '/usr/local/lib/python2.7/dist-packages/cryptography-2.4.2-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/cffi-1.11.5-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/asn1crypto-0.24.0-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/idna-2.8-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/pycparser-2.19-py2.7.egg', '/home/ugv-yu/catkin_ws/devel/lib/python2.7/dist-packages', '/home/ugv-yu/Autoware/ros/devel/lib/python2.7/dist-packages', '/opt/ros/kinetic/lib/python2.7/dist-packages', '/usr/share/qgis/python', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/ugv-yu/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk2']
['/home/ugv-yu/bryan/Frenet/frenet/python', '/usr/local/lib/python2.7/dist-packages/cryptography-2.4.2-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/cffi-1.11.5-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/asn1crypto-0.24.0-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/idna-2.8-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/pycparser-2.19-py2.7.egg', '/home/ugv-yu/catkin_ws/devel/lib/python2.7/dist-packages', '/home/ugv-yu/Autoware/ros/devel/lib/python2.7/dist-packages', '/opt/ros/kinetic/lib/python2.7/dist-packages', '/usr/share/qgis/python', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/ugv-yu/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk2']
Create Frenet Main Window
('create DynamicsWidget', <PySide2.QtWidgets.QWidget object at 0x7f231cc6df80>)
(u'new MplWidget', <PySide2.QtWidgets.QWidget object at 0x7f231cc6df80>)
Traceback (most recent call last):
  File "main.py", line 24, in <module>
    oFrenetMainWindow = fmw.FrenetMainWindow()
  File "/home/ugv-yu/bryan/Frenet/frenet/python/gui/frenet_main_window.py", line 7, in __init__
    self.setupUi(self)
  File "/home/ugv-yu/bryan/Frenet/frenet/python/gui/ui/frenet_main_window_ui.py", line 25, in setupUi
    self.dynamics_widget = DynamicsWidget(self.centralwidget)
  File "/home/ugv-yu/bryan/Frenet/frenet/python/gui/widgets/dynamics_widget.py", line 18, in __init__
    super(DynamicsWidget, self).__init__(self.oFig, parent)
  File "/home/ugv-yu/bryan/Frenet/frenet/python/gui/widgets/mplwidget.py", line 25, in __init__
    self.canvas = MplCanvas(i_oFig)                  # Create canvas object
  File "/home/ugv-yu/bryan/Frenet/frenet/python/gui/widgets/mplwidget.py", line 17, in __init__
    Canvas.setSizePolicy(self, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
TypeError: arguments did not match any overloaded call:
  QWidget.setSizePolicy(QSizePolicy): argument 2 has unexpected type 'PySide2.QtWidgets.QSizePolicy.Policy'
  QWidget.setSizePolicy(QSizePolicy.Policy, QSizePolicy.Policy): argument 2 has unexpected type 'PySide2.QtWidgets.QSizePolicy.Policy'

When I use python main.py in terminal, the above is unfolded there. I think there is an mismatch for PySide2 library maybe. The following is shown in my terminal.

>>> import PySide2
>>> print(PySide2.__version__)
2.0.0~alpha0

Transform between cartesian and frenet coordinate system

Hi @fjp , I'm working on my own version of this algorithm to generate a local path to avoid obstacles.
Currently I have a problem which I have no idea about how to fix. Here is the image to show my problem, the pink path is the original reference path, the left blue path is the generated path to avoid the obstacle lies on the original path, and the red circle marks my problem. When I try to convert my path from Frenet coordinate (s, d) to Cartesian coordinate (x, y), sometimes the path will suddenly turn back like the red circle part shows.
frenet_frame_bug

I use the spline function to map between s-to-x and s-to-y according to the original reference path. And I calculate the new path point which has d distance away from the original reference path and is perpendicular to the tangent direction of the relative point on the original path. I think the problem is coming from the curvature of the original path, but I have no idea about how to fix it. Can you give me some suggestion?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.