carla
carla copied to clipboard
The topology generated from Map is not usable with networkx
CARLA version: 0.9.12 Platform/OS: Ubunut 20.04
I the documentation: https://carla.readthedocs.io/en/latest/python_api/#methods_28 says that: get_topology(self) Returns a list of tuples describing a minimal graph of the topology of the OpenDRIVE file. The tuples contain pairs of waypoints located either at the point a road begins or ends. The first one is the origin and the second one represents another road end that can be reached. This graph can be loaded into NetworkX to work with. Output could look like this: [(w0, w1), (w0, w2), (w1, w3), (w2, w3), (w0, w4)].
Return: list(tuple([carla.Waypoint](https://carla.readthedocs.io/en/latest/python_api/#carla.Waypoint), [carla.Waypoint](https://carla.readthedocs.io/en/latest/python_api/#carla.Waypoint)))
But the following code is not working:
print("Drawing topology over the map..")
topology = tmp_map.get_topology()
graph = nx.Graph()
graph.add_edges_from(topology,object=id)
print("Topology Pairs: ", len(topology))
print("Node: ",graph.number_of_nodes(),graph.nodes)
print("Edges: ",graph.number_of_edges(),graph.edges)
Topology Pairs: 503 Node: 1006 Edges: 503
This is because the eq and ne Dunder methods are not provided which will compare the "id" attribute of to see if the nodes are same.
I have made some changes to get it to work with networkx.
class WaypointTransform:
def __init__(self,id,transform: carla.Transform):
self.id = id
self.transform = transform
def __eq__(self,other) -> bool:
return self.id == other.id
def __ne__(self,other) -> bool:
return self.id != other.id
def __hash__(self) -> int:
return self.id
def __str__(self) -> str:
return str(self.id) #+ ":" + str(self.transform)
...
for index in range(len(topology)):
#print(index, topology[index])
start_waypoint = topology[index][0]
end_waypoint = topology[index][1]
topology_connected.append((WaypointTransform(start_waypoint.id,start_waypoint.transform),WaypointTransform(end_waypoint.id,end_waypoint.transform)))
But there is no Eulerian Circuit in the Graph:
graph = nx.Graph()
graph.add_edges_from(topology_connected)
print("Topology Pairs: ", len(topology_connected))
print("Node: ",graph.number_of_nodes(), graph.nodes)
print("Edges: ",graph.number_of_edges(),graph.edges)
if nx.is_eulerian(graph):
print([u for u, v in nx.eulerian_circuit(graph)])
else:
print(graph,"is NOT Eulerian?")
nx.write_graphml_lxml(graph,"topology_connected.graphml")
Hey @RaviBeagle, not sure if it helps, as I'm not really following what you mean about the eq and ne methods, but CARLA has a global route planner, which uses the topology to create a networkx graph here. I've been using it for a long time and it seems to be working fine for me
Hi @glopezdiest,
Thanks. That was a useful script. My original need was to see if there was an Eulerian path or circuit in the topology that I could use such that I am able to create the PCD map of all the Towns Main need: PCD Map of all Towns with Intensity data.
sampling_resolution = 3
global_planner = GlobalRoutePlanner(tmp_map, sampling_resolution)
start_pose = tmp_map.get_spawn_points()[SPAWN_POINTS[i_map - 1]]
start_location = start_pose.location
end_location = start_pose.location
route = global_planner.trace_route(start_location, end_location)
print(route)
print(f"Size of graph |n| = {len(global_planner._graph.nodes)}, |e| = {len(global_planner._graph.edges)}")
if nx.is_eulerian(global_planner._graph):
print(f"Graph {global_planner._wmap} has an eulerian circuit:")
#nx.write_graphml_xml(global_planner._graph,f"{map_name}.graphml"
print(global_planner._graph)
else:
print(f"Graph {global_planner._wmap} does not have an eulerian circuit")
Hi @glopezdiest,
Thanks. That was a useful script. My original need was to see if there was an Eulerian path or circuit in the topology that I could use such that I am able to create the PCD map of all the Towns Main need: PCD Map of all Towns with Intensity data.
sampling_resolution = 3 global_planner = GlobalRoutePlanner(tmp_map, sampling_resolution) start_pose = tmp_map.get_spawn_points()[SPAWN_POINTS[i_map - 1]] start_location = start_pose.location end_location = start_pose.location route = global_planner.trace_route(start_location, end_location) print(route) print(f"Size of graph |n| = {len(global_planner._graph.nodes)}, |e| = {len(global_planner._graph.edges)}") if nx.is_eulerian(global_planner._graph): print(f"Graph {global_planner._wmap} has an eulerian circuit:") #nx.write_graphml_xml(global_planner._graph,f"{map_name}.graphml" print(global_planner._graph) else: print(f"Graph {global_planner._wmap} does not have an eulerian circuit")
Hi, when I use an OpenDRIVE file as the map for Carla, the world.get_map().get_topology() in global planner will be empty. Do you know the reason?