Message Boards Message Boards

Generate a point to the left side of the direction between two points?

Posted 6 years ago

Hi guys,

I am trying to make a Traffic Simulator for my bachelor thesis. But, i have a problem, i don't know how to keep the correct side of road for every car, all my cars are on the same side of road. I am thinking about the direction between two points and the car will be at the right side of the direction. But I have no idea how to do this....

The road is created with points, every point is a spatial point (x,y,z).

Thank you!

Attachment

Attachments:
POSTED BY: Zavalichi Razvan
9 Replies

The question is a little vague, so I will have some fun with this. You can make normals by switching tangents. For example, if the tangent t = {t1, t2} then the normal will be n = {-t2, t1}. With this in mind, we can make a roads generator with left and right using the following function:

makeRoad[ centerPointsList_, width_, id_] := 
 Module[ { numberOfPoints, pairs, tangents, normals, leftBorder, 
   rightBorder, pointLocatorOnRoad, normalLocatorOnRoad},
  numberOfPoints = Length[ centerPointsList ];
  pairs = 
   With[ {p = Partition[ centerPointsList, 2, 1 ]}, 
    Append[ p, Last[ p ] ] ];
  tangents = Normalize[ #[[2]] - #[[1]] ] & /@ pairs;
  normals = {-#[[2]], #[[1]]} & /@ tangents;
  leftBorder = 
   Table[ centerPointsList[[i]] + normals[[i]] * width /2, {i, 1, 
     Length[ normals]}];
  rightBorder = 
   Table[ centerPointsList[[i]] - normals[[i]] * width /2, {i, 1, 
     Length[ normals]}];
  pointLocatorOnRoad  = 
   With[ {localPointMap = 
      Thread[ {Range[ 0, 1, 1/(numberOfPoints - 1) ], 
        centerPointsList} ]},
    Interpolation[ localPointMap, InterpolationOrder -> 1 ] ];
  normalLocatorOnRoad = 
   With[ {localPointMap = 
      Thread[ {Range[ 0, 1, 1/(numberOfPoints - 1) ], normals} ]},
    Interpolation[ localPointMap, InterpolationOrder -> 01 ] ];

  $roadDatabase[id, "road" ] = {Line[ leftBorder ], 
    Line[ rightBorder ], Dashed, Line[ centerPointsList ]};
  $roadDatabase[ id, "locate", s_ ] :=  pointLocatorOnRoad[ s ];
  $roadDatabase[ id, "pointMid", s_ ] := { 
    Disk[ pointLocatorOnRoad[ s ], width / 4 ]};
  $roadDatabase[ id, "pointLeft", s_ ] := { 
    Disk[ pointLocatorOnRoad[ s ] + 
      normalLocatorOnRoad[ s ] * width / 4 , width / 4 ]};
  $roadDatabase[ id, "pointRight", s_ ] := { 
    Disk[ pointLocatorOnRoad[ s ] - 
      normalLocatorOnRoad[ s ] * width / 4 , width / 4 ]};

  Graphics[ $roadDatabase[id, "road" ] ]
  ]

Evaluate above then, let's test it:

makeRoad[ Table[ {i, i^2}, {i, 0, 2, 0.2} ], 0.2, 1 ];
makeRoad[ 
  Table[ {3, 2} + 2 {Cos[\[Theta]], Sin[\[Theta]]}, {\[Theta], 0, 
    2 \[Pi], 2 \[Pi] / 64}  ], 0.2, 2 ];
Manipulate[
 Graphics[ {$roadDatabase[1, "road" ], $roadDatabase[2, "road" ],
   Red, $roadDatabase[ 1, "pointLeft", i ], 
   Blue, $roadDatabase[ 1, "pointRight", 1 - i ],
   Red, $roadDatabase[ 2, "pointLeft", i ], 
   Blue, $roadDatabase[ 2, "pointRight", 1 - i ]} ],
 {{i, 0}, 0, 1} ]

Above can be cleaned up to have $roadDatabase hidden and only accessed through some interface. You can also add other graphic primitives to put on your roads (as many as you want with each road being independent). It would be fun having objects for cars too and so on ... but fun is over. Hope this helps.

POSTED BY: Nabil Fares

Oh, my mistake, I am very tired.
The road has two lanes, left and right.
I can create a road with two points, like this: a-------------------------------b
The line which is created by the points a and b is midle of the road.

Now, I have the point c which is the car în my program.
Initial the point is on the line a-----------------c----------------b
If direction of the car (point c) is a->b I whant to put the car in the right lane, and if the direction of the car is b->a I want to put the car in the left lane.

Like this:
a->b -----------------------------------
c

a<-b
c
a<-b -----------------------------------
I know how to put the car on the correct lane, but I don't know when to do it

I was thinking about the direction, and to put every time a point to right side of the direction of two points, so my car will be all time on the correct lane of road

POSTED BY: Zavalichi Razvan

Much easier! Use the Cross to get the cross product (distinguishes right from left :) between your vector and the normal to the ground, and this will give you the normal direction you need pointing always right or always left (depending on order used). In 2-D, I used it in my previous reply to get a normal from a tangent. In your case, if v is your direction then {-v[[2]], v[[1]]} is the direction pointing right.

POSTED BY: Nabil Fares

I believe that {-v[[2]],v[[1]]} is to the left of the velocity vector {v[[1]],v[[2]]}. Note that it also has the same length as the velocity, so to get an offset to the position, you need to normalize it, negate it, and multiply by the offset from the center of the road. The offset you want to use depends on both how you want your display to look and what the lane structure of the road is. For instance, if we ignore pretty, a road with a shared center lane for left turners would have an offset of zero for the shared lane, and an offset of the lane width for the first direction-dedicated lane, 2 lane widths for the next and so on. A typical road does not have such a shared special purpose lane, so you might want to use 1/2 the lane width for the offset of the leftmost lane in each direction, 3/2 the lane width for the second and so on.

POSTED BY: dan Erickson

True, it’s to the left which is what I used in the code of my first reply to position the cars and where I also used Normalize to work with unit vectors and I also used width over 4 to place dots in the middle of their lanes ... and it’s also fun to look at but it seems no one checked it out :( ... In my second reply, I got sloppy because I was typing on my iPhone which I’m doing again :) ...

POSTED BY: Nabil Fares

I found this solution:

car.progressPosition = Vector3.MoveTowards(car.progressPosition, car.path[car.index].point + lane, Time.deltaTime * speed);
car.car.transform.position = car.progressPosition+car.car.transform.right*2;

POSTED BY: Zavalichi Razvan

I'm not sure that I understand your formulation.

Did you intend A to be the projection of the car's position onto the line that is the center of the road and p1 to be it's current specific position taking into account its direction of travel?

Did you consider the following?

Left and right don't work in three dimensions. Unless you want to simulate banked turns or such, you can assume that the road is flat left-to-right and use just the x and y components to calculate the offset. If A is (ax, ay, az) and B is (bx, by, bz) then the unit vector to the right is (ay-by, bx-ax, 0).normalized . You would multiply this by the number of lanes from the center and the lane width to get the offset and then add this offset to A to get the adjusted car position and add it to B to get the adjusted destination.

If A is the car position and B is the road center for its next destination point, why would you need to calculate a move from B to A? A car going the opposite direction from the same current position would have a different destination point.

POSTED BY: dan Erickson

Because my cars are generated random. A to B, B to A, A to D, D to C to B to A. But I found the solution

POSTED BY: Zavalichi Razvan

I see. Congratulations on finding a solution!

POSTED BY: dan Erickson
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract