michele-segata / plexe

Repository for Plexe
GNU General Public License v2.0
49 stars 39 forks source link

Plexe various questions #44

Open RaffaeleTranfaglia opened 6 months ago

RaffaeleTranfaglia commented 6 months ago

Hello, I am trying to install plexe on my system (MacOs M2 Sonoma). I am facing the following error when executing:

cd ~/src/omnetpp-<your version>
./configure

The error it gives is:

checking if all necessary Python modules are available... no
configure: error: Some Python modules required by the IDE were not found: numpy scipy pandas matplotlib posix_ipc

In the Building section of the Plexe website it is mentioned to substitute the setenv file, but the link is not working for me. What should I do?

I also tried to use Instant Plexe on UTM (converting OVA file in the extension UTM uses) but it is really slow and unreactive so it is impossible for me to use. Have you got any advice on which way is best for me? I would like to use Plexe for my Bachelor's thesis. Thank you in advance.

michele-segata commented 6 months ago

Thanks for spotting the error and most importantly the 404 on the website. The 404 was due to an additional 's' in the URL that I fixed. The correct URL is http://plexe.car2x.org/download/setenv. But before that, I would first start by adding the missing python libraries. I might have not experienced such error because I already had them installed. Simply install them with

pip install --user numpy scipy pandas matplotlib posix_ipc

or

sudo pip install numpy scipy pandas matplotlib posix_ipc

depending on whether you want to install them system-wide or not.

RaffaeleTranfaglia commented 6 months ago

Ok, thank you. Regarding the Plexe Python module for SUMO, is it necessary to build plexe from the source files or is it already integrated in SUMO?

I am referring to something like this:

from plexe import ACC, CACC
michele-segata commented 6 months ago

It is already integrated in SUMO. But if you use the Python interface, you won't have the simulation of communications.

RaffaeleTranfaglia commented 6 months ago

I am using SUMO 1.19.0 version (installed using homebrew). I have non problems in importing TraCi module, but when I try to import Plexe, it raise the following error:

Import "plexe" could not be resolved

Am I doing something wrong?

michele-segata commented 6 months ago

Did you install the Python API following the README in the official repo?

RaffaeleTranfaglia commented 6 months ago

Thanks, I actually was missing that step.

Regarding the yield rules, how platoons interact with other vehicles (or other platoons)? In particular, let us say there is a platoon composed by 10 vehicles (coming from a minor route) which is crossing a junction and in that moment an external car approach from a different (major) lane. How the external car know when the entire platoon has finished crossing, in order to pass? Is it something that radar and lidar sensors take into account, so the external car will pass when it does not detect any more vehicles crossing?

I hope I have been clear in explaining the situation.

michele-segata commented 6 months ago

Simple and sad answer, they don't know about each other. Unless the external car is a human-driven vehicle, they might simply collide. The only way platoons interact and are aware of each other is longitudinally. The leader is driven by an ACC, so if it approaches a slower vehicle it will slow down. They are also partially aware of adjacent lanes meaning that they should change lane only if the adjacent lane is free and only if you tell a platoon to do so or if you enable the automatic lane change feature. Notice however that we are currently working on the lane change feature as it has known bugs and there can still be collisions. We should release patches soon, but we're still doing testing at the moment.

Coming back to your point, the idea is that any advanced cooperative maneuver (say, intersection crossing) requires coordination among vehicles and this needs to be implemented on top of Plexe. It is like taking a real car, activating the ACC and then approaching a red semaphone. The car won't slow down. We have an active project on cooperative maneuvers, so this is still an open issue.

RaffaeleTranfaglia commented 5 months ago

A question regarding the Plexe API, given the following method to change a vehicle following model in order to add it to a platoon

plexe.set_active_controller(vid, CACC)

How does the vehicle vid know who is the leader, given the fact that CACC model also depends on leader attributes like its speed? Maybe using set_cacc_parameters()?

I tried to implement a method to create a platoon given the leader and a list of vehicles which are behind it. Am I missing something? I saw the add_member() method, should I use it to add a member to a platoon?

""" 
create a platoon of n vehicles
:param lid: leader id
:param vids: list of members' ids to add to the platoon
:return: returns the topology of the platoon, i.e., a dictionary which
indicates, for each vehicle, who is its leader and who is its front
vehicle.
"""
def create_platoon(self, lid, vids):
    traci.vehicle.setSpeedMode(lid, 0)
    traci.vehicle.setColor(vid, [random.randint(0, 254) for x in range(3)].append(1))
    self.plexe.set_active_controller(vid, ACC)
    topology = {}
    for i in range(len(vids)):
        vid = vids[i]
        traci.vehicle.setSpeedMode(vid, 0)
        traci.vehicle.setColor(vid, traci.vehicle.getColor(lid))
        self.plexe.set_active_controller(vid, CACC)
        self.plexe.set_path_cacc_parameters(vid, distance=DISTANCE)
        topology[vid] = {"front" : vids[i], "leader" : lid}
    return topology

In general, taking a look at Plexe API implementation it seems a traci wrapper to handling better the following models. Am I correct? In that case, is the comunication side (Omnet++ side) not handled in the python module?

Thank you for your time.

michele-segata commented 5 months ago

If you look at the Python examples, you can either use "auto feeding", as shown here or you will have to fake communication by passing data manually to the members. See here and here.

RaffaeleTranfaglia commented 5 months ago

In Plexe API, what constant variable represents CC controller? I need to set the controller back to CC when the platoon formation is freed. Regarding the leader, should he be always set to ACC? Whenever I try to set the leader to ACC (in the platoon creation), when the vehicle is waiting before the traffic light junction, it pass through even if the light is red. I also tried to set it to DRIVER, it does not pass at red lights, but for some reason the members do not start at the same moment of the leader.

michele-segata commented 5 months ago

In Plexe API, what constant variable represents CC controller? I need to set the controller back to CC when the platoon formation is freed.

There is no pure cruise control (CC), only adaptive cruise control (ACC). If you would like to have pure CC, then you should modify the logic in SUMO, which is not too complicated.

Regarding the leader, should he be always set to ACC? Whenever I try to set the leader to ACC (in the platoon creation), when the vehicle is waiting before the traffic light junction, it pass through even if the light is red. I also tried to set it to DRIVER, it does not pass at red lights, but for some reason the members do not start at the same moment of the leader.

The fact that the ACC passes with the red light is intended behavior, as it would do in real life. If you switch to DRIVER, the problem is that currently the model does not share the required data with the followers, as it is not an automated controller. This is not in principle an impossible problem. Here I am suggesting other people how to do that, but it seems nobody tried. The idea of open sourcing all this would be to enable anyone to add features and then merge them in the main release. So if you work this out, let me know.

RaffaeleTranfaglia commented 5 months ago

In order to modify the controller logic, is it necessary to make changes in SUMO source code? Right now I am working with the Homebrew based installation of SUMO.

Talking about CC, how is it different from DRIVER? I saw that in the definition of vType in rou.xml file it is possible to set carFollowModel="CC", so is it allowed to simply pass "CC" as an argument to setparameter() in order to change to CC?

michele-segata commented 5 months ago

In order to modify the controller logic, is it necessary to make changes in SUMO source code? Right now I am working with the Homebrew based installation of SUMO.

Yes, you would need to clone SUMO from github, edit the code and recompile it. However, before doing it, you might want to check whether you can simply fetch the required data (such as acceleration and speed) of the leader that is using DRIVER anyhow using the TraCI API, and pass them to the controller of the followers.

Talking about CC, how is it different from DRIVER? I saw that in the definition of vType in rou.xml file it is possible to set carFollowModel="CC", so is it allowed to simply pass "CC" as an argument to setparameter() in order to change to CC?

Wait, here there is a misconception. CC is the car following model I implemented for SUMO that includes several control algorithms (ACC, plus a set of CACCs). You can switch between different controllers using the setActiveController() API. In addition to this, using the same API, you can tell the model to behave like a human vehicle. Please check the official API documentation.

RaffaeleTranfaglia commented 5 months ago

Yes, you would need to clone SUMO from github, edit the code and recompile it. However, before doing it, you might want to check whether you can simply fetch the required data (such as acceleration and speed) of the leader that is using DRIVER anyhow using the TraCI API, and pass them to the controller of the followers.

Shouldn't the plexe.set_leader_vehicle_data() and plexe.get_vehicle_data() methods already do the fetching and setting of speed and acceleration even if the leader is using DRIVER? Actually through TraCI API is possible to get the speed and acceleration of a vehicle, to pass those parameters to the controller I believe setParameter() method is needed, but it is the same method used by plexe.set_leader_vehicle_data().

Wait, here there is a misconception. CC is the car following model I implemented for SUMO that includes several control algorithms (ACC, plus a set of CACCs). You can switch between different controllers using the setActiveController() API. In addition to this, using the same API, you can tell the model to behave like a human vehicle. Please check the official API documentation.

Now it is clearer to me, thank you. Is there a paper or a documentation page for faked and ploeg CACC?

michele-segata commented 5 months ago

Yes, you would need to clone SUMO from github, edit the code and recompile it. However, before doing it, you might want to check whether you can simply fetch the required data (such as acceleration and speed) of the leader that is using DRIVER anyhow using the TraCI API, and pass them to the controller of the followers.

Shouldn't the plexe.set_leader_vehicle_data() and plexe.get_vehicle_data() methods already do the fetching and setting of speed and acceleration even if the leader is using DRIVER? Actually through TraCI API is possible to get the speed and acceleration of a vehicle, to pass those parameters to the controller I believe setParameter() method is needed, but it is the same method used by plexe.set_leader_vehicle_data().

Yes you can use plexe.set_leader_vehicle_data() but plexe.get_vehicle_data() works only when using ACC/CACCs. As you suggest, you might try getting speed and acceleration using classic TraCI APIs, it should not be impossible, but nobody tried. If you can give it a try and let me know, it would be great.

Wait, here there is a misconception. CC is the car following model I implemented for SUMO that includes several control algorithms (ACC, plus a set of CACCs). You can switch between different controllers using the setActiveController() API. In addition to this, using the same API, you can tell the model to behave like a human vehicle. Please check the official API documentation.

Now it is clearer to me, thank you. Is there a paper or a documentation page for faked and ploeg CACC?

Faked CACC is the same as CACC, the only difference is that you feed the distance manually instead of picking the one of the radar, and you use set_leader_vehicle_fake_data() and set_front_vehicle_fake_data(). W.r.t. to documentation, see articles number 12 and 13 in the references page.

RaffaeleTranfaglia commented 5 months ago

Yes you can use plexe.set_leader_vehicle_data() but plexe.get_vehicle_data() works only when using ACC/CACCs. As you suggest, you might try getting speed and acceleration using classic TraCI APIs, it should not be impossible, but nobody tried. If you can give it a try and let me know, it would be great.

I noticed that plexe.get_vehicle_data() return the right speed and acceleration values even for DRIVER vehicles (that is because using TraCi methods the retrieved values are the same). The following data are the result of plexe.get_vehicle_data() for each vehicle composing a platoon.

leader vehicle data:
        index: None
        u: 0
        acceleration: 4.58387
        speed: 0.936323
        pos_x: -1.6
        pos_y: 14.4596
        time: 130.2
        length: None
vehicle: flow2.0
vehicle: flow2.1
front vehicle data:
        index: None
        u: 0
        acceleration: 4.58387
        speed: 0.936323
        pos_x: -1.6
        pos_y: 14.4596
        time: 130.2
        length: None
vehicle: flow2.2
front vehicle data:
        index: None
        u: 0.13471
        acceleration: 0.0224516
        speed: 0.00224516
        pos_x: -1.6
        pos_y: 20.6414
        time: 130.2
        length: None
vehicle: flow2.3
front vehicle data:
        index: None
        u: 0
        acceleration: 0
        speed: 0
        pos_x: -1.6
        pos_y: 26.6906
        time: 130.2
        length: None

Nevertheless there is something wrong. The speed and acceleration of the leader are not propagated through the entire platoon at the same time. The following clip shows the behaviour of the platoon.

https://github.com/michele-segata/plexe/assets/117942523/67bd0d31-83bd-41f7-898f-b2799cae726b

It emerges a kind of cooperation but it is not the ideal situation where the last vehicle starts moving at the same time of the leader.

I am currently using the following settings for the vehicles:

<vType id="auto" accel="5" decel="10" sigma="0.0" length="4"
        minGap="2" maxSpeed="36" color="255,255,255" probability="1"
        carFollowModel="CC" tauEngine="0.5" omegaN="0.2" xi="1" c1="0.5"
        lanesCount="4" ccAccel="4" ploegKp="0.2" ploegKd="0.7"
        ploegH="0.5"/>

There is no specific reason why I am using these parameters, I have taken them from a different project. Is there a recommended set of parameters for the vehicles? I have also tried to use a more generic vType definition

<vType id="auto" color="255,255,255" carFollowModel="Krauss" sigma="0.0" minGap="2"/>

but it raises the following error on creating the platoon (in particular when plexe.set_active_controller(lid, DRIVER) is executed):

traci.exceptions.TraCIException: Vehicle 'flow1.0' does not support carFollowModel parameter 'carFollowModel.ccac' (Setting parameter 'ccac' is not supported by carFollowModel).
michele-segata commented 5 months ago

Yes you can use plexe.set_leader_vehicle_data() but plexe.get_vehicle_data() works only when using ACC/CACCs. As you suggest, you might try getting speed and acceleration using classic TraCI APIs, it should not be impossible, but nobody tried. If you can give it a try and let me know, it would be great.

I noticed that plexe.get_vehicle_data() return the right speed and acceleration values even for DRIVER vehicles (that is because using TraCi methods the retrieved values are the same). The following data are the result of plexe.get_vehicle_data() for each vehicle composing a platoon.

Yes, I cross-checked that and indeed that works. However, u does not work because this is the acceleration computed by the automated controller, and in case of the DRIVER mode there is none. See later why.

leader vehicle data:
        index: None
        u: 0
        acceleration: 4.58387
        speed: 0.936323
        pos_x: -1.6
        pos_y: 14.4596
        time: 130.2
        length: None
vehicle: flow2.0
vehicle: flow2.1
front vehicle data:
        index: None
        u: 0
        acceleration: 4.58387
        speed: 0.936323
        pos_x: -1.6
        pos_y: 14.4596
        time: 130.2
        length: None
vehicle: flow2.2
front vehicle data:
        index: None
        u: 0.13471
        acceleration: 0.0224516
        speed: 0.00224516
        pos_x: -1.6
        pos_y: 20.6414
        time: 130.2
        length: None
vehicle: flow2.3
front vehicle data:
        index: None
        u: 0
        acceleration: 0
        speed: 0
        pos_x: -1.6
        pos_y: 26.6906
        time: 130.2
        length: None

Nevertheless there is something wrong. The speed and acceleration of the leader are not propagated through the entire platoon at the same time. The following clip shows the behaviour of the platoon. Screen.Recording.2024-04-27.at.12.32.40.mov

It emerges a kind of cooperation but it is not the ideal situation where the last vehicle starts moving at the same time of the leader.

Now here the problem might be the following. There is the possibility of using, in the CACC control law, either the real acceleration or the acceleration of the controller (the u I was mentioning before). The acceleration of the controller is pre-engine actuation, which gives the controller a higher reactivity. If this is enabled in your case, then u is always set to 0, so the controller performs bad. To be sure that this is disabled, call the plexe.use_controller_acceleration(<vehicle id>, False) API at the very beginning for every vehicle. See if this changes the behavior.

I am currently using the following settings for the vehicles:

<vType id="auto" accel="5" decel="10" sigma="0.0" length="4"
      minGap="2" maxSpeed="36" color="255,255,255" probability="1"
      carFollowModel="CC" tauEngine="0.5" omegaN="0.2" xi="1" c1="0.5"
      lanesCount="4" ccAccel="4" ploegKp="0.2" ploegKd="0.7"
      ploegH="0.5"/>

There is no specific reason why I am using these parameters, I have taken them from a different project. Is there a recommended set of parameters for the vehicles? I have also tried to use a more generic vType definition

<vType id="auto" color="255,255,255" carFollowModel="Krauss" sigma="0.0" minGap="2"/>

but it raises the following error on creating the platoon (in particular when plexe.set_active_controller(lid, DRIVER) is executed):

traci.exceptions.TraCIException: Vehicle 'flow1.0' does not support carFollowModel parameter 'carFollowModel.ccac' (Setting parameter 'ccac' is not supported by carFollowModel).

No, this will never work. This way you are instantiating a normal human vehicle within SUMO, which provides no Plexe API.

RaffaeleTranfaglia commented 5 months ago

Now here the problem might be the following. There is the possibility of using, in the CACC control law, either the real acceleration or the acceleration of the controller (the u I was mentioning before). The acceleration of the controller is pre-engine actuation, which gives the controller a higher reactivity. If this is enabled in your case, then u is always set to 0, so the controller performs bad. To be sure that this is disabled, call the plexe.use_controller_acceleration(, False) API at the very beginning for every vehicle. See if this changes the behavior.

It actually worked, the latency between the leader start and the other members is near to zero. But now there is an issue occurring sometimes and I cannot understand if it is related to the inter-vehicle distance (plexe.set_path_cacc_parameters(vid, distance=cls.DISTANCE)) or to the propagation of the real acceleration value (plexe.use_controller_acceleration(vid, False)).

https://github.com/michele-segata/plexe/assets/117942523/6d94e7f2-94e2-4a95-8632-229cb9b160ad

As you can see, it seems the members are notified of the leader's deceleration too late. I cannot tell if it is due to the use of real acceleration (instead of the controller one) or if it is due to some issues in setting the inter-vehicle distance of the platoon.

No, this will never work. This way you are instantiating a normal human vehicle within SUMO, which provides no Plexe API.

To instantiate an autonomous vehicle should I set the carFollowModel to a CC controller?

michele-segata commented 5 months ago

Now here the problem might be the following. There is the possibility of using, in the CACC control law, either the real acceleration or the acceleration of the controller (the u I was mentioning before). The acceleration of the controller is pre-engine actuation, which gives the controller a higher reactivity. If this is enabled in your case, then u is always set to 0, so the controller performs bad. To be sure that this is disabled, call the plexe.use_controller_acceleration(, False) API at the very beginning for every vehicle. See if this changes the behavior.

It actually worked, the latency between the leader start and the other members is near to zero. But now there is an issue occurring sometimes and I cannot understand if it is related to the inter-vehicle distance (plexe.set_path_cacc_parameters(vid, distance=cls.DISTANCE)) or to the propagation of the real acceleration value (plexe.use_controller_acceleration(vid, False)). Screen.Recording.2024-05-01.at.21.00.40.mov

As you can see, it seems the members are notified of the leader's deceleration too late. I cannot tell if it is due to the use of real acceleration (instead of the controller one) or if it is due to some issues in setting the inter-vehicle distance of the platoon.

I made a test by modifying the brake demo. In particular, I changed the deceleration of the leader to 8 m/s/s instead of 6 m/s/s, and checked what changes by using or not the controller acceleration. The difference is huge. When using the controller acceleration, the minimum distance between the leader and the second vehicle is 3.9 m, whereas when not using it, the second vehicle is 0.95 meters from the leader. So I guess this is what happens in your simulations as well, and it is to be expected.

No, this will never work. This way you are instantiating a normal human vehicle within SUMO, which provides no Plexe API.

To instantiate an autonomous vehicle should I set the carFollowModel to a CC controller?

Yes.

RaffaeleTranfaglia commented 5 months ago

I made a test by modifying the brake demo. In particular, I changed the deceleration of the leader to 8 m/s/s instead of 6 m/s/s, and checked what changes by using or not the controller acceleration. The difference is huge. When using the controller acceleration, the minimum distance between the leader and the second vehicle is 3.9 m, whereas when not using it, the second vehicle is 0.95 meters from the leader. So I guess this is what happens in your simulations as well, and it is to be expected.

Yes, it is what happened in my simulations. But why is to be expected? Is there a way to avoid the collision? I tried the brake demo using plexe.use_controller_acceleration(vid, False) and -8 m/s/s as acceleration value. The result is similar to mine simulation but no vehicles collide, even after incrementing the acceleration to -20 m/s/s.

michele-segata commented 5 months ago

I made a test by modifying the brake demo. In particular, I changed the deceleration of the leader to 8 m/s/s instead of 6 m/s/s, and checked what changes by using or not the controller acceleration. The difference is huge. When using the controller acceleration, the minimum distance between the leader and the second vehicle is 3.9 m, whereas when not using it, the second vehicle is 0.95 meters from the leader. So I guess this is what happens in your simulations as well, and it is to be expected.

Yes, it is what happened in my simulations. But why is to be expected? Is there a way to avoid the collision? I tried the brake demo using plexe.use_controller_acceleration(vid, False) and -8 m/s/s as acceleration value. The result is similar to mine simulation but no vehicles collide, even after incrementing the acceleration to -20 m/s/s.

Can you check what is the maximum deceleration of your human driven vehicle? BTW, by setting the deceleration to my vehicles as -20 m/s/s they won't brake that hard because the maximum deceleration is set to 8. The best thing here is to always try to look at actual values to have a comparison and try to understand what are the differences.

RaffaeleTranfaglia commented 5 months ago

My vehicles should have a maximum deceleration of 10. By the way you are right about the brake demo, i tried to set the maximum deceleration to 20 and it occurred a collision. However, I also tried to set it to 10 (the value of my simulation) and there isn't any collision, but I think it is due to a lower vehicles speed.

The best thing here is to always try to look at actual values to have a comparison and try to understand what are the differences.

Thank you for the advice.

RaffaeleTranfaglia commented 5 months ago

Is there a way to make a platoon member start moving only when its distance from the front vehicle is equal to a fixed value? That is because my vehicles stop at the minGap distance from the front vehicle. Accordingly, whenever the platoon is created the inter-vehicle distance is minGap. As soon as the front vehicle decelerate then the distance falls below minGap and eventually the simulation threat that as a collision. If I could set a distance of minGap+offset even if there is a deceleration it can be handled (whithin a certain limit). I tried using plexe.set_path_cacc_parameters(vid, distance=cls.DISTANCE) but I think it only sets the maximun distance between members.

michele-segata commented 5 months ago

For platooning vehicles the minGap should be set to 0. In fact, the plexe.set_path_cacc_parameters(vid, distance=cls.DISTANCE) call sets the distance vehicles must maintain, not a minimum, not a maximum. Fluctuations in that distance are normal, as vehicles cannot immediately implement control actions. What you can do is increasing that cls.DISTANCE value.

RaffaeleTranfaglia commented 5 months ago

For platooning vehicles the minGap should be set to 0.

I imagined that as it is set to zero in brake demo. As soon as the platoon members are selected, their minGap is set to 0. But for vehicles which are not included in the platoon I think is useful to have a minGap greater than zero.

What you can do is increasing that cls.DISTANCE value.

I tried to increase that value but the result is the same. The inter-vehicle distance remains the same as when they stop before crossing. As it can be seen in the following clip, in the second platoon the last member is teleported because of a collision, even if its minGap is 0.

https://github.com/michele-segata/plexe/assets/117942523/1674355b-121f-4fcd-be89-e1ada271a53b

I also noticed that the distance between members tends to be shorter towards the end of the platoon, although I believe it should be approximately the same in every part of the platoon. In addition, in the first platoon that crosses the junction there is a member that change lane even if is still a member of the platoon. Is it normal?

The method I use to create a platoon is the following:

@classmethod
def create_platoon(cls, vids: list[str], plexe: Plexe) -> dict[str, dict[str, str]]:
        """
        Create a platoon of n vehicles.

        Args:
            vids (list[str]): list of members0 ids to add to the platoon
            plexe (Plexe): API instance

        Returns:
            dict[str, dict[str, str]]: the topology of the platoon, i.e., a dictionary which
            indicates, for each vehicle, who is its leader and who is its front vehicle.
        """
        lid = vids[0]
        print(f"Creating a platoon composed of {lid} {vids}")
        traci.vehicle.setSpeedMode(lid, 31)
        color = tuple(random.randint(0, 254) for x in range(3)) + (255,)
        traci.vehicle.setColor(lid, color=color)
        plexe.set_active_controller(lid, DRIVER)
        plexe.use_controller_acceleration(lid, False)
        topology = {}
        topology[lid] = {"front" : None, "leader" : lid}
        for i in range(1, len(vids)):
            vid = vids[i]
            traci.vehicle.setMinGap(vid, 0)
            frontvid = vids[i-1]
            traci.vehicle.setSpeedMode(vid, 0)
            traci.vehicle.setColor(vid, traci.vehicle.getColor(lid))
            plexe.set_active_controller(vid, CACC)
            plexe.use_controller_acceleration(vid, False)
            plexe.set_path_cacc_parameters(vid, distance=cls.DISTANCE)
            topology[vid] = {"front" : frontvid, "leader" : lid}
        return topology

where vids[0] is the leader.

michele-segata commented 5 months ago

For platooning vehicles the minGap should be set to 0.

I imagined that as it is set to zero in brake demo. As soon as the platoon members are selected, their minGap is set to 0. But for vehicles which are not included in the platoon I think is useful to have a minGap greater than zero.

Yes, that is correct.

What you can do is increasing that cls.DISTANCE value.

I tried to increase that value but the result is the same. The inter-vehicle distance remains the same as when they stop before crossing. As it can be seen in the following clip, in the second platoon the last member is teleported because of a collision, even if its minGap is 0.

I don't see the collision... anyhow, minGap set to 0 won't prevent collisions. It actually adds to the actual distance, so if you set a target distance of 5m but you have a minGap of 2m, the actual distance will be 7m. So better set it to 0 for platooning vehicles.

Screen.Recording.2024-05-08.at.15.58.41.mov

I also noticed that the distance between members tends to be shorter towards the end of the platoon, although I believe it should be approximately the same in every part of the platoon.

Well not really. Shorter in which sense? You should always compare the distance to the target one by measuring it, not looking at it. If the target distance is 5 m, the further you go down the platoon, the more the vehicles will be able to maintain such target regardless of disturbances occurring at the head of the platoon. This is what is called string stability of a platoon. If at the end, the distance is always around 5 meters, then everything is working as expected.

In addition, in the first platoon that crosses the junction there is a member that change lane even if is still a member of the platoon. Is it normal?

No it is not. I suggest upgrading to SUMO 1.20.0. We fixed the lane change model. After upgrading please be sure to add every vehicle as member of a specific platoon using the addPlatoonMember() API. Let me know if this happens again.

The method I use to create a platoon is the following:

@classmethod
def create_platoon(cls, vids: list[str], plexe: Plexe) -> dict[str, dict[str, str]]:
        """
        Create a platoon of n vehicles.

        Args:
            vids (list[str]): list of members0 ids to add to the platoon
            plexe (Plexe): API instance

        Returns:
            dict[str, dict[str, str]]: the topology of the platoon, i.e., a dictionary which
            indicates, for each vehicle, who is its leader and who is its front vehicle.
        """
        lid = vids[0]
        print(f"Creating a platoon composed of {lid} {vids}")
        traci.vehicle.setSpeedMode(lid, 31)
        color = tuple(random.randint(0, 254) for x in range(3)) + (255,)
        traci.vehicle.setColor(lid, color=color)
        plexe.set_active_controller(lid, DRIVER)
        plexe.use_controller_acceleration(lid, False)
        topology = {}
        topology[lid] = {"front" : None, "leader" : lid}
        for i in range(1, len(vids)):
            vid = vids[i]
            traci.vehicle.setMinGap(vid, 0)
            frontvid = vids[i-1]
            traci.vehicle.setSpeedMode(vid, 0)
            traci.vehicle.setColor(vid, traci.vehicle.getColor(lid))
            plexe.set_active_controller(vid, CACC)
            plexe.use_controller_acceleration(vid, False)
            plexe.set_path_cacc_parameters(vid, distance=cls.DISTANCE)
            topology[vid] = {"front" : frontvid, "leader" : lid}
        return topology

where vids[0] is the leader.

RaffaeleTranfaglia commented 4 months ago

I updated to version 1.20.0. Using DRIVER controller on the leader and the following code to add members:

for i in range(1, len(vids)):
            vid = vids[i]
            traci.vehicle.setMinGap(vid, 0)
            frontvid = vids[i-1]
            traci.vehicle.setColor(vid, traci.vehicle.getColor(lid))
            topology[vid] = {"front" : frontvid, "leader" : lid}
            plexe.add_member(lid, vid, i)
            plexe.use_controller_acceleration(vid, False)
            plexe.set_path_cacc_parameters(vid, distance=cls.DISTANCE)

where lid is leader id and cls.DISTANCE is 2. This is to add platoon members using the method you suggested (if there is something else to explicitly set, like SpeedMode to 0 or the active controller for the members please let me know).

The second platoon showed in the last video is behaving this way. As soon as the traffic lights turn green, the platoon in created, inter-vehicle distance is equal to the previous minGap (which has been set to zero in the platoon creation) which is 2m. In addition, every member is communicating with the leader and the front vehicle to get the real speed and acceleration.

flow2.1 flow2.0
Distance: 2.050316816155828
flow2.2 flow2.1
Distance: 1.9999635644232399
flow2.3 flow2.2
Distance: 2.0013238368885595
flow2.4 flow2.3
Distance: 2.001282818808363
flow2.5 flow2.4
Distance: 2.000861909365028
flow2.6 flow2.5
Distance: 2.001362664808312
flow2.7 flow2.6
Distance: 2.0005515425569342
flow2.8 flow2.7
Distance: 2.0006606694905713
flow2.9 flow2.8
Distance: 2.0009305065456147
flow2.10 flow2.9
Distance: 2.001411779797877
flow2.11 flow2.10
Distance: 2.0012056094001878
flow2.12 flow2.11
Distance: 2.000363231521362
flow2.13 flow2.12
Distance: 2.001421352449256
flow2.14 flow2.13
Distance: 2.0013016606155816
flow2.15 flow2.14
Distance: 2.001441411491271
flow2.16 flow2.15
Distance: 2.065858768966791
leader vehicle data:
        index: None
        u: 0
        acceleration: 2.36759
        speed: 0.483807
        pos_x: -1.6
        pos_y: 14.5279
        time: 110.2
        length: None
vehicle: flow2.0
vehicle: flow2.1
front vehicle data:
        index: None
        u: 0
        acceleration: 2.36759
        speed: 0.483807
        pos_x: -1.6
        pos_y: 14.5279
        time: 110.2
        length: None
vehicle: flow2.2
front vehicle data:
        index: None
        u: 0
        acceleration: 2.37783
        speed: 0.237783
        pos_x: -1.6
        pos_y: 20.5782
        time: 110.2
        length: None
vehicle: flow2.3
front vehicle data:
        index: None
        u: 0
        acceleration: 2.48242
        speed: 0.248242
        pos_x: -1.6
        pos_y: 26.5782
        time: 110.2
        length: None
vehicle: flow2.4
front vehicle data:
        index: None
        u: 0
        acceleration: 2.451
        speed: 0.2451
        pos_x: -1.6
        pos_y: 32.5795
        time: 110.2
        length: None
vehicle: flow2.5
front vehicle data:
        index: None
        u: 0
        acceleration: 2.4237
        speed: 0.24237
        pos_x: -1.6
        pos_y: 38.5808
        time: 110.2
        length: None
vehicle: flow2.6
front vehicle data:
        index: None
        u: 0
        acceleration: 2.43844
        speed: 0.243844
        pos_x: -1.6
        pos_y: 44.5817
        time: 110.2
        length: None
vehicle: flow2.7
front vehicle data:
        index: None
        u: 0
        acceleration: 2.40314
        speed: 0.240314
        pos_x: -1.6
        pos_y: 50.583
        time: 110.2
        length: None
vehicle: flow2.8
front vehicle data:
        index: None
        u: 0
        acceleration: 2.44894
        speed: 0.244894
        pos_x: -1.6
        pos_y: 56.5836
        time: 110.2
        length: None
vehicle: flow2.9
front vehicle data:
        index: None
        u: 0
        acceleration: 2.4838
        speed: 0.24838
        pos_x: -1.6
        pos_y: 62.5842
        time: 110.2
        length: None
vehicle: flow2.10
front vehicle data:
        index: None
        u: 0
        acceleration: 2.49165
        speed: 0.249165
        pos_x: -1.6
        pos_y: 68.5852
        time: 110.2
        length: None
vehicle: flow2.11
front vehicle data:
        index: None
        u: 0
        acceleration: 2.45139
        speed: 0.245139
        pos_x: -1.6
        pos_y: 74.5866
        time: 110.2
        length: None
vehicle: flow2.12
front vehicle data:
        index: None
        u: 0
        acceleration: 2.43183
        speed: 0.243183
        pos_x: -1.6
        pos_y: 80.5878
        time: 110.2
        length: None
vehicle: flow2.13
front vehicle data:
        index: None
        u: 0
        acceleration: 2.49641
        speed: 0.249641
        pos_x: -1.6
        pos_y: 86.5881
        time: 110.2
        length: None
vehicle: flow2.14
front vehicle data:
        index: None
        u: 0
        acceleration: 2.45525
        speed: 0.245525
        pos_x: -1.6
        pos_y: 92.5896
        time: 110.2
        length: None
vehicle: flow2.15
front vehicle data:
        index: None
        u: 0
        acceleration: 2.42599
        speed: 0.242599
        pos_x: -1.6
        pos_y: 98.5909
        time: 110.2
        length: None
vehicle: flow2.16
front vehicle data:
        index: None
        u: 0
        acceleration: 2.42577
        speed: 0.243098
        pos_x: -1.6
        pos_y: 104.592
        time: 110.2
        length: None

This is the situation after few steps. The fixed distance is not maintained and is increasing as we look at the head of the platoon.

flow2.1 flow2.0
Distance: 32.076770115225074
flow2.2 flow2.1
Distance: 16.700663916916128
flow2.3 flow2.2
Distance: 14.572327570496462
flow2.4 flow2.3
Distance: 15.869844479112821
flow2.5 flow2.4
Distance: 13.497547395174967
flow2.6 flow2.5
Distance: 9.493927760837645
flow2.7 flow2.6
Distance: 8.691236555684759
flow2.8 flow2.7
Distance: 7.857996868065774
flow2.9 flow2.8
Distance: 7.038951085342944
flow2.10 flow2.9
Distance: 6.21532068193136
flow2.11 flow2.10
Distance: 5.429725443513917
flow2.12 flow2.11
Distance: 4.669830213764442
flow2.13 flow2.12
Distance: 4.008557369074197
flow2.14 flow2.13
Distance: 3.4555252919219015
flow2.15 flow2.14
Distance: 2.9824142246206407
flow2.16 flow2.15
Distance: 2.6435690107254004
leader vehicle data:
        index: None
        u: 0
        acceleration: 1.91766
        speed: 23.3416
        pos_x: 135.33
        pos_y: -1.6
        time: 122.4
        length: None
vehicle: flow2.0
vehicle: flow2.1
front vehicle data:
        index: None
        u: 0
        acceleration: 1.91766
        speed: 23.3416
        pos_x: 135.33
        pos_y: -1.6
        time: 122.4
        length: None
vehicle: flow2.2
front vehicle data:
        index: None
        u: 0
        acceleration: 2.21135
        speed: 19.9307
        pos_x: 99.2528
        pos_y: -1.6
        time: 122.4
        length: None
vehicle: flow2.3
front vehicle data:
        index: None
        u: 0
        acceleration: 2.33649
        speed: 18.0022
        pos_x: 78.5521
        pos_y: -1.6
        time: 122.4
        length: None
vehicle: flow2.4
front vehicle data:
        index: None
        u: 0
        acceleration: 1.47112
        speed: 16.4822
        pos_x: 59.9798
        pos_y: -1.6
        time: 122.4
        length: None
vehicle: flow2.5
front vehicle data:
        index: None
        u: 0
        acceleration: 2.36199
        speed: 14.0841
        pos_x: 40.11
        pos_y: -1.6
        time: 122.4
        length: None
vehicle: flow2.6
front vehicle data:
        index: None
        u: 0
        acceleration: 1.55393
        speed: 10.9915
        pos_x: 22.6124
        pos_y: -1.6
        time: 122.4
        length: None
vehicle: flow2.7
front vehicle data:
        index: None
        u: 0
        acceleration: 0.8847
        speed: 10.0192
        pos_x: 9.16285
        pos_y: -0.966121
        time: 122.4
        length: None
vehicle: flow2.8
front vehicle data:
        index: None
        u: 0
        acceleration: 1.30673
        speed: 9.21531
        pos_x: -0.330551
        pos_y: 6.41759
        time: 122.4
        length: None
vehicle: flow2.9
front vehicle data:
        index: None
        u: 0
        acceleration: 1.43894
        speed: 8.31887
        pos_x: -1.6
        pos_y: 18.1207
        time: 122.4
        length: None
vehicle: flow2.10
front vehicle data:
        index: None
        u: 0
        acceleration: 1.31599
        speed: 7.37065
        pos_x: -1.6
        pos_y: 29.1597
        time: 122.4
        length: None
vehicle: flow2.11
front vehicle data:
        index: None
        u: 0
        acceleration: 0.377376
        speed: 6.52409
        pos_x: -1.6
        pos_y: 39.375
        time: 122.4
        length: None
vehicle: flow2.12
front vehicle data:
        index: None
        u: 0
        acceleration: 1.72033
        speed: 5.725
        pos_x: -1.6
        pos_y: 48.8047
        time: 122.4
        length: None
vehicle: flow2.13
front vehicle data:
        index: None
        u: 0
        acceleration: 0.816418
        speed: 4.77942
        pos_x: -1.6
        pos_y: 57.4746
        time: 122.4
        length: None
vehicle: flow2.14
front vehicle data:
        index: None
        u: 0
        acceleration: 1.14545
        speed: 4.11749
        pos_x: -1.6
        pos_y: 65.4831
        time: 122.4
        length: None
vehicle: flow2.15
front vehicle data:
        index: None
        u: 0
        acceleration: 0.58877
        speed: 3.46686
        pos_x: -1.6
        pos_y: 72.9386
        time: 122.4
        length: None
vehicle: flow2.16
front vehicle data:
        index: None
        u: 0
        acceleration: -0.274648
        speed: 2.96835
        pos_x: -1.6
        pos_y: 79.9211
        time: 122.4
        length: None

Is there something I am missing in setting the platoon? I also noticed that the problem where platoon members change lane is still occurring when using an ACC controller on the leader. When the leader is using DRIVER it has not happened yet.

michele-segata commented 4 months ago

I tried some more testing. I edited the brakingdemo.py as you see below. The leader vehicle brakes for 10 seconds and then goes back to its speed:

import os
import sys
import random
from build.lib.plexe import DRIVER
from utils import add_platooning_vehicle, start_sumo, running, communicate

if 'SUMO_HOME' in os.environ:
    tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
    sys.path.append(tools)
else:
    sys.exit("please declare environment variable 'SUMO_HOME'")
import traci
from plexe import Plexe, ACC, CACC, RPM, GEAR, RADAR_DISTANCE, RADAR_REL_SPEED

# vehicle length
LENGTH = 4
# inter-vehicle distance
DISTANCE = 5
# cruising speed
SPEED = 120/3.6
# distance between multiple platoons
PLATOON_DISTANCE = SPEED * 1.5 + 2
# vehicle who starts to brake
BRAKING_VEHICLE = "v.0.0"

def add_vehicles(plexe, n, n_platoons, real_engine=False):
    """
    Adds a set of platoons of n vehicles each to the simulation
    :param plexe: API instance
    :param n: number of vehicles of the platoon
    :param n_platoons: number of platoons
    :param real_engine: set to true to use the realistic engine model,
    false to use a first order lag model
    :return: returns the topology of the platoon, i.e., a dictionary which
    indicates, for each vehicle, who is its leader and who is its front
    vehicle. The topology can the be used by the data exchange logic to
    automatically fetch data from leading and front vehicle to feed the CACC
    """
    # add a platoon of n vehicles
    topology = {}
    p_length = n * LENGTH + (n - 1) * DISTANCE
    for p in range(n_platoons):
        for i in range(n):
            vid = "v.%d.%d" % (p, i)
            add_platooning_vehicle(plexe, vid, (n-p+1) *
                                   (p_length + PLATOON_DISTANCE) + (n-i+1) *
                                   (DISTANCE+LENGTH), 0, SPEED, DISTANCE,
                                   real_engine)
            plexe.set_fixed_lane(vid, 0, False)
            traci.vehicle.setSpeedMode(vid, 0)
            plexe.use_controller_acceleration(vid, False)
            if i == 0:
                plexe.set_active_controller(vid, DRIVER)
            else:
                plexe.set_active_controller(vid, CACC)
            if i > 0:
                topology[vid] = {"front": "v.%d.%d" % (p, i - 1),
                                 "leader": "v.%d.0" % p}
            else:
                topology[vid] = {}
    return topology

def main(demo_mode, real_engine, setter=None):
    # used to randomly color the vehicles
    random.seed(1)
    start_sumo("cfg/freeway.sumo.cfg", False)
    plexe = Plexe()
    step = 0
    topology = dict()
    out = open("log.csv", "w")
    out.write("nodeId,time,distance,relativeSpeed,speed,acceleration,controllerAcceleration\n")

    while running(demo_mode, step, 6000):

        # when reaching 60 seconds, reset the simulation when in demo_mode
        if demo_mode and step == 6000:
            start_sumo("cfg/freeway.sumo.cfg", True)
            step = 0
            random.seed(1)

        traci.simulationStep()

        if step == 0:
            # create vehicles and track the braking vehicle
            topology = add_vehicles(plexe, 8, 1, real_engine)
            traci.gui.trackVehicle("View #0", BRAKING_VEHICLE)
            traci.gui.setZoom("View #0", 20000)
        if step % 10 == 1:
            # simulate vehicle communication every 100 ms
            communicate(plexe, topology)
        if real_engine and setter is not None:
            # if we are running with the dashboard, update its values
            tracked_id = traci.gui.getTrackedVehicle("View #0")
            if tracked_id != "":
                ed = plexe.get_engine_data(tracked_id)
                vd = plexe.get_vehicle_data(tracked_id)
                setter(ed[RPM], ed[GEAR], vd.speed, vd.acceleration)
        if step == 500:
            plexe.set_fixed_acceleration(BRAKING_VEHICLE, True, -20)
            traci.vehicle.setAcceleration(BRAKING_VEHICLE, -4, 10)
        if step > 1:
            vehicles = traci.vehicle.getIDList()
            for v in vehicles:
                if v == BRAKING_VEHICLE:
                    distance = -1
                    rel_speed = 0
                else:
                    radar = plexe.get_radar_data(v)
                    distance = radar[RADAR_DISTANCE]
                    rel_speed = radar[RADAR_REL_SPEED]
                acc = traci.vehicle.getAcceleration(v)
                out.write(f"{v},{step},{distance},{rel_speed},{traci.vehicle.getSpeed(v)},{acc},{acc}\n")

        step += 1

    out.close()
    traci.close()

if __name__ == "__main__":
    main(False, False)

This creates a platoon with a leader which uses DRIVER. In addition, I am logging the data of vehicles to log.csv so that they can be plotted. I also edited the sigma and the maxSpeed parameter of the vehicle type:

<routes>
    <vType id="vtypeauto" accel="2.5" decel="8" sigma="0" length="4" tau="3.0"
           minGap="0" maxSpeed="33.33" color="1,0,0" probability="1"
           carFollowModel="CC" tauEngine="0.5" omegaN="0.2" xi="1" c1="0.5"
           lanesCount="4" ccAccel="1.5" ploegKp="0.2" ploegKd="0.7"
           ploegH="0.5" speedFactor="2" laneChangeModel="LC2013_CC"
           lcStrategic="5" lcCooperative="5" lcSpeedGain="5" lcKeepRight="5"/>
    <route id="platoon_route" edges="edge_0_0 edge_0_1 edge_0_2 edge_0_3 edge_1_0 edge_1_1 edge_1_2 edge_1_3 edge_2_0 edge_2_1 edge_2_2 edge_2_3 edge_3_0 edge_3_1 edge_3_2 edge_3_3 edge_4_0 edge_4_1 edge_4_4 edge_4_6 absorption_4"/>
</routes>

Then I tried to plot the data using the following R script:

library(ggplot2)
allData <- read.csv("log.csv")
allData$controllerName <- "CACC"

p.speed <- ggplot(allData, aes(x=time, y=speed*3.6, col=factor(nodeId))) +
           geom_line() +
           facet_grid(controllerName~., scales='free_y')
ggsave('braking-speed.pdf', p.speed, width=16, height=9)

p.distance <- ggplot(subset(allData, distance != -1), aes(x=time, y=distance, col=factor(nodeId))) +
              geom_line() +
              facet_grid(controllerName~., scales='free_y')
ggsave('braking-distance.pdf', p.distance, width=16, height=9)

p.accel <- ggplot(allData, aes(x=time, y=acceleration, col=factor(nodeId))) +
           geom_line() +
           facet_grid(controllerName~., scales='free_y')
ggsave('braking-acceleration.pdf', p.accel, width=16, height=9)

Obtaining the following plots: braking-speed.pdf braking-distance.pdf braking-acceleration.pdf

First you can see that the human model introduces noise in the acceleration, which is something SUMO does and that for sure affects the CACC vehicles. It should be reduced by setting sigma=0. Second, the distance does not deviate too much from the 5 meter target. Can you try this setup? For the lane change issue, we need to check later.

RaffaeleTranfaglia commented 4 months ago

I tried the setup. It is definitely working better now, that is probably because I previously used add_member() instead of add_platooning_vehicle by mistake. I looked at the implementation of add_platooning_vehicle, what does plexe.set_acc_headway_time(v, 1.5) do?

Below are the measures taken from two platoons of my simulation. In my case, a platoon is cleared after each member cross the intersection, so it is actually living for a bunch of seconds. That is why the time period is so limited. It seems the trend it is following the one in your graphs. I set the sigma in the vehicles to 0, but there is still much noise in the acceleration.

Environment:

Platoon-acceleration-graph Platoon-acceleration-graph2 Platoon-distance-graph Platoon-distance-graph2 Platoon-speed-graph Platoon-speed-graph2

Regarding the fact that we are using the actual acceleration, does the following rule for CACC vehicles still apply? If I understood correctly, that should be the controller acceleration of the i-th member. And if it is correct, after obtaining the desired acceleration, is the controller speed computed from it?

image
michele-segata commented 4 months ago

I tried the setup. It is definitely working better now, that is probably because I previously used add_member() instead of add_platooning_vehicle by mistake. I looked at the implementation of add_platooning_vehicle, what does plexe.set_acc_headway_time(v, 1.5) do?

It sets the time headway for the ACC algorithm, but given that you are not using it, it has no effect.

Below are the measures taken from two platoons of my simulation. In my case, a platoon is cleared after each member cross the intersection, so it is actually living for a bunch of seconds. That is why the time period is so limited. It seems the trend it is following the one in your graphs. I set the sigma in the vehicles to 0, but there is still much noise in the acceleration.

What do you mean with "a platoon is cleared after each member cross the intersection"? Does that mean they are not using CACC anymore? What do you switch to? Switching to another controller at such small distances can lead to collisions.

Environment:

* Inter-vehicle distance = 3

* the platoon is created from a queue of vehicle where the distance from the front is 2

* each platoon is starting from a stationary state, i.e. at t=0, speed=0 and acceleration=0 for each member

Regarding the fact that we are using the actual acceleration, does the following rule for CACC vehicles still apply? If I understood correctly, that should be the controller acceleration of the i-th member. And if it is correct, after obtaining the desired acceleration, is the controller speed computed from it?

I don't know if I understood your question correctly. Are you asking whether I can use the controller acceleration of CACC vehicles to feed other CACC vehicles? So using the real acceleration of the leader and the controller acceleration of the preceding vehicle? You can do it by simply passing as actual acceleration of the preceding vehicle its controller acceleration, but honestly I don't know what happens from a stability perspective using inconsistent data. Give it a try though.

RaffaeleTranfaglia commented 4 months ago

What do you mean with "a platoon is cleared after each member cross the intersection"? Does that mean they are not using CACC anymore? What do you switch to? Switching to another controller at such small distances can lead to collisions.

The scope of my project is to exploit the platoon members' cooperation in order to optimise the throughput of an intersection controlled by a traffic light and the total waiting time of the vehicles. Given a queue of stationary vehicles waiting for the green light, my idea is to create a platoon of vehicles which have to turn the same way. When the entire platoon has passed the intersection, it is cleared, i. e. the members controller change from CACC to the one they previously had. Ideally the controller should be the one defined in the vtype:

<vType id="vtypeauto" accel="2.5" decel="8" sigma="0" length="4"
        minGap="2" maxSpeed="36" color="255,255,255" probability="1"
        carFollowModel="CC" tauEngine="0.5" omegaN="0.2" xi="1" c1="0.5"
        lanesCount="4" ccAccel="4" ploegKp="0.2" ploegKd="0.7"
        ploegH="0.5"/>

but given the fact that I am not sure on how to set it properly, I currently am setting the controller to DRIVER when the platoons are cleared. If I understood correctly DRIVER is a krauss follwing model so it is the nearest thing to the standard autonomous vehicle. The following clip shows the logic:

https://github.com/michele-segata/plexe/assets/117942523/e72dd1da-6fc5-40fc-8609-01f353f4495c

With a careful management of the minGap and the platoon inter vehicle distance, even if the controller is switched at a small distance, no collision occurs, on the worst case only a brake. I hope the project direction is clearer now. The only problem I am facing now is that sometimes a member (or more than one) change lane and so the data propagated to the rest of the platoon are wrong. I cannot tell the reason behind it, but from my debug prints I noticed that at some point its acceleration and its speed does not change accordingly to the information passed from the front, but they remain unchanged for the rest of the platoon life. The phenomenon is also visible from the clip above. Perhaps explicitly setting void enableAutoLaneChanging(bool enable) to false could solve the problem?

I don't know if I understood your question correctly. Are you asking whether I can use the controller acceleration of CACC vehicles to feed other CACC vehicles? So using the real acceleration of the leader and the controller acceleration of the preceding vehicle? You can do it by simply passing as actual acceleration of the preceding vehicle its controller acceleration, but honestly I don't know what happens from a stability perspective using inconsistent data. Give it a try though.

My doubt is about the way acceleration and speed are computed when using real acceleration and speed. On the plexe paper is show the rule for computing the desired acceleration in a CACC vehicle. So what change in that formula when the real acceleration is passed? Does it remain unchanged apart from x0 and xi-1 which are the real values and not the controller ones?

michele-segata commented 4 months ago

What do you mean with "a platoon is cleared after each member cross the intersection"? Does that mean they are not using CACC anymore? What do you switch to? Switching to another controller at such small distances can lead to collisions.

The scope of my project is to exploit the platoon members' cooperation in order to optimise the throughput of an intersection controlled by a traffic light and the total waiting time of the vehicles. Given a queue of stationary vehicles waiting for the green light, my idea is to create a platoon of vehicles which have to turn the same way. When the entire platoon has passed the intersection, it is cleared, i. e. the members controller change from CACC to the one they previously had. Ideally the controller should be the one defined in the vtype:

<vType id="vtypeauto" accel="2.5" decel="8" sigma="0" length="4"
      minGap="2" maxSpeed="36" color="255,255,255" probability="1"
      carFollowModel="CC" tauEngine="0.5" omegaN="0.2" xi="1" c1="0.5"
      lanesCount="4" ccAccel="4" ploegKp="0.2" ploegKd="0.7"
      ploegH="0.5"/>

but given the fact that I am not sure on how to set it properly, I currently am setting the controller to DRIVER when the platoons are cleared. If I understood correctly DRIVER is a krauss follwing model so it is the nearest thing to the standard autonomous vehicle. The following clip shows the logic: With a careful management of the minGap and the platoon inter vehicle distance, even if the controller is switched at a small distance, no collision occurs, on the worst case only a brake. I hope the project direction is clearer now.

Yes, it is clear. However, switching the control directly from a CACC at a very small distance to Krauss (which is basically giving the control back to the driver) is not safe. In the real world this would lead to collisions, even with autonomous cars, because the distance is simply too small and you are suddenly losing important information (what the leader is doing) which is what enables you to maintain a constant spacing gap policy. Basically, you are suddenly switching from a constant spacing policy to constant time headway policy, which can cause instabilities and collisions. What this will do is generate a deceleration shockwave that will cause sooner or later a collision. The fact that they do not collide does not mean things are safe, because the Krauss model is basically collision free, so SUMO will brake unrealistically hard to avoid the collision, but in the real world they will crash into each other. If you want to switch to another controller, you should first progressively increase the distance, and then switch.

The only problem I am facing now is that sometimes a member (or more than one) change lane and so the data propagated to the rest of the platoon are wrong. I cannot tell the reason behind it, but from my debug prints I noticed that at some point its acceleration and its speed does not change accordingly to the information passed from the front, but they remain unchanged for the rest of the platoon life. The phenomenon is also visible from the clip above. Perhaps explicitly setting void enableAutoLaneChanging(bool enable) to false could solve the problem?

Yes you can give it a try. But without looking deeply into it I cannot really understand why this is happening.

I don't know if I understood your question correctly. Are you asking whether I can use the controller acceleration of CACC vehicles to feed other CACC vehicles? So using the real acceleration of the leader and the controller acceleration of the preceding vehicle? You can do it by simply passing as actual acceleration of the preceding vehicle its controller acceleration, but honestly I don't know what happens from a stability perspective using inconsistent data. Give it a try though.

My doubt is about the way acceleration and speed are computed when using real acceleration and speed. On the plexe paper is show the rule for computing the desired acceleration in a CACC vehicle. So what change in that formula when the real acceleration is passed? Does it remain unchanged apart from x0 and xi-1 which are the real values and not the controller ones?

The formula does not change, you just use a different value.

RaffaeleTranfaglia commented 4 months ago

Yes, it is clear. However, switching the control directly from a CACC at a very small distance to Krauss (which is basically giving the control back to the driver) is not safe. In the real world this would lead to collisions, even with autonomous cars, because the distance is simply too small and you are suddenly losing important information (what the leader is doing) which is what enables you to maintain a constant spacing gap policy. Basically, you are suddenly switching from a constant spacing policy to constant time headway policy, which can cause instabilities and collisions. What this will do is generate a deceleration shockwave that will cause sooner or later a collision. The fact that they do not collide does not mean things are safe, because the Krauss model is basically collision free, so SUMO will brake unrealistically hard to avoid the collision, but in the real world they will crash into each other. If you want to switch to another controller, you should first progressively increase the distance, and then switch.

I see, in fact as soon as the carFollwingModel changes, a deceleration shockwave occurs. The problem is that, given the fact that the platoon is cleared when it passes the intersection, there is not enough time for the members to distance themselves. I tried by setting the inter-vehicle distance of the platoon to 30, it works only for small platoons. Since the benefits of platoon strategy have more effect the larger the platoon is, it would be a waste to limit the platoon size. In addition, using a great distance, the members' departure does not happen at the same moment because of the close distance at which they find themselves when the platoon is created. Perhaps I can use something like traci.vehicle.setAcceleration(BRAKING_VEHICLE, -4, 10) to decrease the speed and make the transition smoother after passing the intersection, instead of immediately switching the controller. Does it make sense to you?

Yes you can give it a try. But without looking deeply into it I cannot really understand why this is happening.

I tried it, but nothing changes. However, in case you would like to take a look at it here is the repository link (Platoon.py and runner.py are the involved files).

The formula does not change, you just use a different value.

Ok, so at every step the desired acceleration is computed. As a result, the actual acceleration is adjusted to meet the desired acceleration, and that is the acceleration and speed passed to the following member when choosing to pass real values. Otherwise, the passed values are the desired ones. Is that right?

michele-segata commented 4 months ago

I see, in fact as soon as the carFollwingModel changes, a deceleration shockwave occurs. The problem is that, given the fact that the platoon is cleared when it passes the intersection, there is not enough time for the members to distance themselves. I tried by setting the inter-vehicle distance of the platoon to 30, it works only for small platoons. Since the benefits of platoon strategy have more effect the larger the platoon is, it would be a waste to limit the platoon size. In addition, using a great distance, the members' departure does not happen at the same moment because of the close distance at which they find themselves when the platoon is created. Perhaps I can use something like traci.vehicle.setAcceleration(BRAKING_VEHICLE, -4, 10) to decrease the speed and make the transition smoother after passing the intersection, instead of immediately switching the controller. Does it make sense to you?

It would not help in my opinion, because you are doing a lot of work to improve traffic flow and then, to dismantle the platoon, you slow everyone down. I guess here the good thing to do is to keep the platoon, not dismantling it immediately after crossing. Or, in any case, take more time to dismantle that.

Just a question on this. Are you doing this as bachelor or master thesis? Or as part of a PhD? I guess this kind of details needs to be discussed with your advisor.

Yes you can give it a try. But without looking deeply into it I cannot really understand why this is happening.

I tried it, but nothing changes. However, in case you would like to take a look at it here is the repository link (Platoon.py and runner.py are the involved files).

I see. Call

self.plexe.set_fixed_lane(vid, traci.vehicle.getLaneIndex(vid))

to every platoon member in create_platoon to fix them to their current lane, and then

self.plexe.set_fixed_lane(vid, -1)

in _clear_platoon() to restore lane change.

Ok, so at every step the desired acceleration is computed. As a result, the actual acceleration is adjusted to meet the desired acceleration, and that is the acceleration and speed passed to the following member when choosing to pass real values. Otherwise, the passed values are the desired ones. Is that right?

Exactly.

RaffaeleTranfaglia commented 4 months ago

It would not help in my opinion, because you are doing a lot of work to improve traffic flow and then, to dismantle the platoon, you slow everyone down. I guess here the good thing to do is to keep the platoon, not dismantling it immediately after crossing. Or, in any case, take more time to dismantle that. Just a question on this. Are you doing this as bachelor or master thesis? Or as part of a PhD? I guess this kind of details needs to be discussed with your advisor.

It is a bachelor's thesis. Yes, I will discuss it with my tutor.

I see. Call self.plexe.set_fixed_lane(vid, traci.vehicle.getLaneIndex(vid)) to every platoon member in create_platoon to fix them to their current lane, and then self.plexe.set_fixed_lane(vid, -1) in _clear_platoon() to restore lane change.

self.plexe.set_fixed_lane(vid, traci.vehicle.getLaneIndex(vid)) fix the problem, but self.plexe.set_fixed_lane(vid, -1) raises the following error: traci.exceptions.TraCIException: No lane with index '-1' on road 'junction_end1'.. It seems that the restoration index -1 is taken as the actual lane index instead of a symbol that enables the vehicle to change lane freely.

Exactly.

Thank you.

michele-segata commented 4 months ago

self.plexe.set_fixed_lane(vid, traci.vehicle.getLaneIndex(vid)) fix the problem, but self.plexe.set_fixed_lane(vid, -1) raises the following error: traci.exceptions.TraCIException: No lane with index '-1' on road 'junction_end1'.. It seems that the restoration index -1 is taken as the actual lane index instead of a symbol that enables the vehicle to change lane freely.

My bad! I realized I didn't push the new changes! Can you update from the repo, re-install, and try again?

RaffaeleTranfaglia commented 4 months ago

It works, thank you.

RaffaeleTranfaglia commented 2 months ago

Why in brake example is used traci.vehicle.setAcceleration? Isn't set_fixed_acceleration sufficient?

plexe.set_fixed_acceleration(BRAKING_VEHICLE, True, -20)
traci.vehicle.setAcceleration(BRAKING_VEHICLE, -4, 10)
michele-segata commented 2 months ago

Why in brake example is used traci.vehicle.setAcceleration? Isn't set_fixed_acceleration sufficient?

plexe.set_fixed_acceleration(BRAKING_VEHICLE, True, -20)
traci.vehicle.setAcceleration(BRAKING_VEHICLE, -4, 10)

The first one works on vehicles using MSCFModel_CC, the second on classic "human" vehicles.

RaffaeleTranfaglia commented 2 months ago

I see, that is why plexe.set_fixed_acceleration(BRAKING_VEHICLE, True, -20) does not work with DRIVER model. So is DRIVER considered a classic "human" vehicles model because it uses MSCFModel_Krauss? Can't a Krauss vehicle be autonomous?

michele-segata commented 2 months ago

Krauss is a human behavioral model, so it should mimic a person, not really an autonomous vehicle