Vehicle placement on CityEngine-generated streets.

4742
22
Jump to solution
08-07-2012 06:24 AM
JoshWade
New Contributor II
Hello again 🙂

I am beginning to create driving scenarios for a driving simulator. (For example, on a highway you are traveling at 70mph when suddenly the vehicle in front of you applies the brakes hard). I see that CE uses some mechanism for placing the cars on the roads neatly between the lines (Even on curved roads).

I am hoping that I can use your algorithm for my AI-driven cars. I assume it has something to do with the street network edges as well as the particular attributes of the street?

Any help would be wonderful!

-Josh
Tags (2)
0 Kudos
22 Replies
JoshWade
New Contributor II
When you say to find a line of code to create the marker, do you mean on the Unity side of things? I suppose it would depend on how the street marker data was created/stored. If the markers were each individual gameObjects, then something like the following could be used to instantiate Vector3 objects at each marker: (JavaScript)
      var marker : Vector3; //vector to hold xyz points of marker
      marker = transform.Find("marker_id#").position; //supposing that street markers each have a unique id


Once all of the necessary markers have been instantiated, they can be used by iTween for path following.
0 Kudos
MatthiasBuehler1
Frequent Contributor
ah, sorry, yes.

With Python, I can directly create the JavaScript code ( basically just a text output ) which creates the code you quoted, looping over all markers CE finds.

when you can post 1 example that runs with the correct syntax ( e.g. vector definition ), I can make the code generic and directly feed the positions.
0 Kudos
JoshWade
New Contributor II
Thanks for all your help so far, by the way!

Here is a potential class definition for a Marker object:
public class Marker {
     /* MEMBER DATA */
     public var m_vector : Vector3; //coordinates
     public var m_id : int; //unique id for each marker

}


Then this function (effectively a constructor) might be applicable:
function instantiateMarker ( x : float, y : float, z : float, id : int) {

     var markerObj : Marker;
     markerObj = new Marker();
     markerObj.m_vector = new Vector3(x,y,z);
     markerObj.m_id = id;

}
0 Kudos
MatthiasBuehler1
Frequent Contributor
so that'd be the result of what CE produces for the markers :

1 street segment with 3 lanes, 4 marker points per lane ( 12 in total )

instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,0);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,1);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,2);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,3);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,4);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,5);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,6);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,7);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,8);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,9);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,10);
instantiateMarker ( 820207.073822,9.48134291172,-72516.0204315,11);


now I assume you run your general CE exports with the offset correction to center the dataset around the cartesian origin in Unity. Once you know that XZ offset, this could be subtracted from the results which you get by the reports.


of course you could run this twice, once just for the right lanes, once just for the left lanes. 🙂

let me know what you think so far.
0 Kudos
JoshWade
New Contributor II
😄 Excellent! Thank you, this seems exactly what I need. And I will be able to run this Python script on my street network (maybe twice for differentiation between left and right lanes) to generate the appropriate points, correct?

I will be centering the points according to Unity's origin. This probably will not be an problem: I can write a script to modify the values according to the level of displacement that occurs.

The example that you have shown me produces 4 points per lane. Will I be able to modify that value if necessary to something higher or lower?
0 Kudos
MatthiasBuehler1
Frequent Contributor
hi !

it uses a distance attribute, thus places markers approximately that distance apart from each other. this example just produced 4.

I'll wrap up the code and post here.
0 Kudos
MatthiasBuehler1
Frequent Contributor
edit the code around line 240 :

1] note the MakeLaneMarkers shape copy after the Vehicles().
2] add the code for the marker creation and position reports

Streetsides -->  case calcNbrOfLanes < 1.1 : Asphalt  case Nbr_of_left_lanes == 0 && Nbr_of_right_lanes == 0:   split(v,unitSpace,0){ ~calcLanesLeft    : Lanes(calcNbrOfLanes,connectionEnd,0) Vehicles(0) MarkerCreation("left")        | Median_width      : Median        | ~calcLanesRight   : scaleUV(0,-1,-1) Lanes(calcNbrOfLanes,connectionStart,2) Vehicles(2) MarkerCreation("right") }  else:   split(v,unitSpace,0){ ~Nbr_of_left_lanes : Lanes(Nbr_of_left_lanes,connectionEnd,0) Vehicles(0) MarkerCreation("left")        | Median_width      : Median        | ~Nbr_of_right_lanes : scaleUV(0,-1,-1) Lanes(Nbr_of_right_lanes,connectionStart,2) Vehicles(2) MarkerCreation("right")}  @Range ( "all", "left", "right") @Group("MARKERS") attr markerOutput = "all"  MarkerCreation(side) -->  case markerOutput == "all" :   MakeLaneMarkers  case markerOutput == side :   MakeLaneMarkers  else :   NIL  MakeLaneMarkers -->  color(1,0,0)  t (0,.1,0)  split(v,unitSpace,0) { ~Lane_width : LaneShape }*  LaneShape -->  split(v,unitSpace,0) { ~1 : NIL | markerDim : LaneCenterLine | ~1 : NIL }  markerDim = 0.25 markerDist = 15  LaneCenterLine -->  split(u,unitSpace,0) {{ markerDim : LaneMarker | ~ markerDist : NIL }* | markerDim : LaneMarker }  LaneMarker -->  report("markerPosX", convert(x, scope, world, pos, 0.5 * scope.sx, 0.5 * scope.sy, 0.5 * scope.sz))  report("markerPosY", convert(y, scope, world, pos, 0.5 * scope.sx, 0.5 * scope.sy, 0.5 * scope.sz))  report("markerPosZ", convert(z, scope, world, pos, 0.5 * scope.sx, 0.5 * scope.sy, 0.5 * scope.sz))  X. # NIL



Now once you generate a street, you should get the reports in the Inspector's Reports tab.

To grab those and produce your java script code :
1] copy the attached .py script to your scripts folder
2] run the Script Based Exporter ( Python ), where you select the new script under the Misc options, then run it.
3] open the console ( Python output ) and get your code.

To adapt the offset, just copy paste your export offset values and edit the Python script accordingly.

I also just added the lane direction switch called (markerOutput).

Note also that now, the markers are produced as geometry, thus you may want to NIL it as commented out in the last line after the reports ( X. # NIL )

let me know if it works on your machine too. 😉
0 Kudos
JoshWade
New Contributor II
Okay, It seems to be working now! Thank you for your help with this. I will let you know if I have any problems.
0 Kudos
JoshWade
New Contributor II
Matthias,
I'm looking at the output more closely now and I'm confused about something. Why are there several markers with the same coordinates, but with different id's? In the example that you posted above, the same thing occurs.

What does it mean?
0 Kudos
MatthiasBuehler1
Frequent Contributor
hmm. I did not test it that thoroughly.

but I assume there's a little issue with the indices in the loop which grabs the corresponding coordinates.

I guess I'd be faster debugging this than you, so I'll try to find the issue.

sry for that .. I'm not a developer .. 🙂
0 Kudos