Closed philippwulff closed 2 years ago
This sounds like the same behavior I needed in #7190. For this reason I added the command setPreviousSpeed. I do the following to get the velocity calculated from SUMO and then adapt the speed to the value from my Simulink model:
Thank you for the quick reply! I will implement it and see if it works for me.
Unfortunately, I could not get it to work. I want the vehicle to drive with the adapted speed, meaning, when I set the vehicle's speed to value
and then call simulationStep()
, the vehicle's speed should be value
.
But when I try the pseudo-code you suggested, the vehicle always has the "SUMO-speed" after simulationStep()
is called instead of the adapted speed.
These are the main calls which I make to replicate your example (and which do not work as I want them to):
while True:
traci.simulationStep()
sumo_speed = traci.vehicle.getSpeedWithoutTraCI(veh_id) # -> get the SUMO-corrected speed for this time step
model_speed = model(sumo_speed) # -> calculate the adjusted speed
traci.vehicle.setPreviousSpeed(veh_id, model_speed) # -> set the adjusted speed for the vehicle
When I run this, the vehicle always has the sumo_speed
as its speed in every time step, instead of the last model_speed
.
From what I understand, after calling simulationStep()
SUMO will correct the PreviousSpeed (which was set before) to a value according to an internal model. However, I only want to know the value for this corrected speed and not have SUMO set the it in the simulation. Preferably, I want to know this value for the next time step, then adjust it and set the vehicle speed in the next time step to this adjusted value. Can you please explain how you do this?
You mentioned moveToXY
. How is that relevant? Why do you have to call moveToXY()
? Doesn't SUMO take care of calculating the new position of the vehicle after having set its speed?
The only way for getting the speed SUMO wants a vehicle to drive in the next time step which I came up with would be using two simulations (sim1 and sim2) and copying the simulation state in between the two after every step. Sim2 would be ahead of sim1 by one time step and SUMO would control the vehicle here to give me the SUMO-speed for it. This is a pretty bad solution and I would rather like to just extract the SUMO-speed from SUMO itself.
This would be the pseudo-code for my idea:
As I said, I would prefer to just extract the value for the nextTraCISpeed from SUMO directly.
If you want to get the speed before SUMO outputs this velocity, then you could use getFollowSpeed
and getStopSpeed
, but as you pointed out, that does not take care of every case.
You are right, setPreviousSpeed
acts the way you described it. For me it is not problematic, because you are getting the internal speed from SUMO and then setting it according to your model yourself. When you change the velocity before the next time step, the calculation behaves, as if this speed was set in the first place.
I call moveTo
or moveToXY
, because the position gets updated with the internal speed and not with the adjusted one. When you do this before the time step, the vehicle then stands at the position it would have had, if it had driven with the adjusted speed as intended. This is a work around for the current way SUMO calculates the speeds of the different vehicles.
For SUMO it does not matter, if you set these variables after the time step or "with" the time step.
@namdre I hope I am not explaining it wrong
@Domsall Yes. That's correct. The core problem that is solved by the workaround of @Domsall is, that the vehicle speed is only known within SUMO after the vehicle has interacted (via junctions) with (potentially) all other vehicles that are approaching the respective junction in the current time step. Whereas the followSpeed is based on the leader state from the previous step, the junction model works on information from the current step and thus cannot be (feasibly) anticipated at the start of the step.
should be documented somewhere maybe from the traci page
@Domsall Just so that I understand how these commands are processed in SUMO:
From this
You are right, setPreviousSpeed acts the way you described it. For me it is not problematic, because you are getting the internal speed from SUMO and then setting it according to your model yourself. When you change the velocity before the next time step, the calculation behaves, as if this speed was set in the first place.
I understand, you call getSpeedWithoutTraCI()
and then setPreviousSpeed()
with your adjusted speed. After calling simulationStep()
SUMO's calculation will assume the vehicle drove with the PreviousSpeed during the entire last time step. If one would however use setSpeed
instead of setPreviousSpeed
, SUMO would not use the given speed for the last time step, right?
In the end you call moveTo()
so that the (manual) calculation of the vehicle position is based upon the adjusted speed and not the internal SUMO speed. However, the vehicle will still have SUMO's internal speed within the simulation during the next time step, even though its position was updated manually with the adjusted speed. This would be a major issue for my use case.
I ended up coding the co-sim-solution to obtain the internal SUMO speed for a vehicle in the next time step and while it is slow, it is working 👍🏽 .
Thanks for your help!
There is an added complication depending on the the use of moveTo / moveToXY in step 3
@Domsall can you confirm the following? :
@philippwulff setSpeed
and setPreviousSpeed
:
setSpeed
sets this speed for future calculations, setPreviousSpeed
, as the name says, sets the speed before the next calculation.speedWithoutTraCI
. You can think of this value as the "setpoint" or "Sollgroesse". If you now use setPreviousSpeed
again, "the last internal speed" is never used for calculation purpose (may still be used somewhere, but not in the main process). Your model (for me Simulink) would always run "behind" SUMO and use the setpoint to adjust the speed with some kind of controller. Right before you call simulationStep
, call setPreviousSpeed
and moveTo
.Or what do you want to do? It is maybe a bit hard to explain it here, you can also write me an E-Mail and we can get together for a talk.
@namdre moveTo
and moveToXY
:
moveTo
does exactly that and that was the desired behavior for me, although the output computation probably uses the speed from speedWithoutTraCI
. But for my part, I do not need any of these computations for the ego-vehicle.moveToXY
was a bit more of a problem. You changed the implementation of speedWithoutTraCI
back then to correctly output the speed calculation of SUMO without the moveToXY
-movement. I have a different implementation for moveToXY
, because I am still getting (almost) the same speedWithoutTraCI
as with moveTo
, but with moveToXY
the Simulink-vehicle's position is now running one step in front of SUMO (instead of one step behind as with moveTo
).I am trying to do what philippwulff did one year ago: use SUMO to provide the target speed for an ego vehicle , feed that target speed to an external vehicle dynamics model, and then feedback the modelled speed to SUMO to calculate the next target speed , and so on. I followed Domsall's recipe and it doesn't work for me either: the target vehicle speed gets stuck on the value the vehicle speed was it entered the network. getSpeedWithoutTraCI seems like the way to go, but when I use it getSpeedWithoutTraCI generates the same value as getSpeed. If In use setSpeed instead of set PreviousSpeed, I get a better behavior where decelerations seem reasonable but accelerations are extremely slow, or if the vehicle gets to a stop at a light it never reaccelerates.
Has any progress been made over the last year on that subject?
setSpeed(vehID, getSpeedWithoutTraCI(vehID))
in every step?If the answer to both is "yes", then the problem may be in the values returned from your external model.
if I don't feedback the modelled speed using setSpeed or setPreviousSpeed, the vehicle drives normally: in this case, it decelerates and stops at a red light, then proceeds to turn right when there is no traffic. when setting speed using setSpeed(vehID, getSpeedWithoutTraCI(vehID)), the vehicle doesn't drive the same way: it decelerates and stops at a red light, but it doesn't re-accelerate normally to turn right, it just creeps forward: it moves 1 or 2 meter over a minute or so and never moves any faster for the rest of the simulation.
Here is a slight correction to my previous post: the vehicle doesn't creep for ever: 300seconds after stopping at the light, it suddenly jumps back to a normal speed and seems to behave normally. I got that behavior and timing on two different ego vehicles stopping at different times and locations on that network.
Can you attach a minimal example of your setup? (traci script and all files needed to run it).
traci.vehicle.setSpeed(idStr, traci.vehicle.getSpeedWithoutTraCI(VehID)) doesn’t work: the vehicle stops at the light and never re-accelerates. But traci.vehicle.setPreviousSpeed(idStr, traci.vehicle.getSpeedWithoutTraCI(VehID)) does work: the vehicle stops at the light and re-accelerates normally.
As soon as I add a simple model to convert the Sumo target speed into an actual vehicle speed (targetspeed= getSpeedWithoutTraCI, speed =f(targetspeed) and setPreviousSpeed(speed)), the vehicle doesn’t behave normally: when using a first order filter vehicle model, it runs thru the light at high speed , and even goes unstable with a one sample delay model.
I am monitoring getSpeed() and getSpeedWithoutTraCI() values, I have not seen them to retrieve different values yet. How can I check that getSpeedWithoutTraCI is working properly?
by the way, I am using SUMO 1.12.0
I have prepared an simple example environment to demonstrate the behavior. how can I share it privately?
@PaulChambonUSA, These functions worked for me just as described above. Unfortunately, I do not know what is causing your issue from the report you give and I am not too familiar with this anymore.
When adding your own controller for the vehicle speed you need to think of the usage of setPreviousSpeed
and moveTo
as correcting the behaviour of the SUMO-internal vehicle control with the values that you want to set for the vehicle speed and location. I say correcting, because you do this after any given time step. Basically you correct the speed and position of the vehicle according to what you want it to be. I made these notes for myself back then, maybe they are of help to you:
Also, you can write code within two "backwards apostrophes" ( ) such that it is easier to read, e.g.
code`.
@philippwulff, thanks for your input. I am still confused as to how it works. Based on the description of ''getSpeedWithoutTraci'', it seems that it should retrieve the speed command as if I hadn't overwritten the new desired speed using setSpeed' but I am yet to see a different value when using getSpeed and getSpeedWithoutTraci.
@namdre, how can I share my test environment with you?
The easiest way is to create a log of traci commands (https://sumo.dlr.de/docs/TraCI/Interfacing_TraCI_from_Python.html#generating_a_log_of_all_traci_commands) and then zip it up with all the simulation input files and attach it to this ticket. Alternatively send it to namdre.sumo at gmail.com
@PaulChambonUSA Here are my findings:
1) My previous suggestion of "does the vehicle drive in the same way as the uncontrolled vehicle when calling setSpeed(vehID, getSpeedWithoutTraCI(vehID)) in every step?" was faulty:
getSpeedWithoutTraCI
retrieves the speed from the previous step and setSpeed
sets the speed for the current step. This means, the actions being enforced this way are always lagging one simulation step behind it's unmodified behavior.
2) the tight update loop is not playing nicely with actionStepLength: when actionStepLength is active for a vehicle, it doesn't update it's desired speed in every step. Instead it computes a desired acceleration in every actionStep and expects to maintain this acceleration until the next actionStep. So when starting from a queue the first actionStep will compute a low desired speed because (just starting to accelerate). Calling setSpeed will then maintain this low speed until the speedWithoutTraCI is slightly increased once the next actionStep comes arround. Basically it divides the acceleration by stepLength/actionStepLength.
I think you could work around issue 2) by
vehicle.setAcceleration(vehID, patchedAcceleration, actionStepLength - stepLength)
@namdre, my TraciAPI files do not define getLastActionTime and getActionStepLength. when I look on the repository: https://github.com/eclipse/sumo/blob/main/src/utils/traci/TraCIAPI.h, I don't see them either. where can I find them?
The code at utils/traci/TraCIAPI.h is no longer actively updated and only kept for backward compatibility. The recommended and feature-complete C++ API is libtraci. See https://sumo.dlr.de/docs/TraCI.html#interfaces_by_programming_language
If you want to do a pull request to add the two missing methods, thats also fine.
I upgraded to libtraci.
I then reset the actionStepLength to 0.1 ( both in the vehicle distribution file and by using setActionStepLength() at each simulation step ). This way we make sure that the issue is not caused by actionStepLength. The behavior is unchanged.
I also tried to use setAccel during accelerations (and keep using setSpeed during decelerations since they seem to work) but the calculated accel is always very very small during accelerations, so the behavior is not much different.
It seems like getSpeedWithoutTraci never requests a re acceleration. Is there a way to look into what getSpeedWithoutTraci is doing to explain the lack of re-acceleration?
I found a bug! https://github.com/eclipse/sumo/issues/10947
A few points from my side after looking into my Code again (I hope this helps):
getSpeedWithoutTraci
instead of getSpeed
because of the moveTo/moveToXY
commands. Without using the move-commands, getSpeedWithoutTraci = getSpeed
should normally be true.getSpeedWithoutTraci
after setting the speed with setSpeed
in the previous step, the value you are getting should be the speed from setSpeed
(see bug report from namdre).setPreviousSpeed(your_calculated_speed)
. The SUMO vehicle will then use this speed for the calculations in the next time step. Because the vehicle actually drove with a different speed in the last step, you will have to change its position, too (as if it had driven with setPreviousSpeed()
). You can do this with moveToXY()/moveTo()
. But you need to do the position/lane/route calulcations yourself. There should be an open issue on this moveTo-topic, too.setPreviousSpeed()
at the beginning of the step and calculates the new speed with the SUMO-model without any influence, which after the step can be read with getSpeedWithoutTraCI().Further comments:
Hi all, I am trying to do exactly what this issue wants to achieve: get the next SUMO speed or acceleration for a vehicle based on SUMO internal behavior models, then use external models to modify SUMO's output control and use movetoXY to update vehicle states.
I am using the 1.19.0 version, but getSpeedWithoutTraCI still cannot output a reasonable value. Are there any updates or suggestions?
are you using traci.executeMove
allready? See #11091
Thanks a lot for the quick response! I haven't, I will look into this and try it out.
Hi @namdre, I tried traci.executeMove
and have a few questions want to make sure. My current pipeline is:
traci.executeMove
to run "half" step of the simulation;getSpeedWithoutTraci
to obtain the SUMO control;A
) controlled by my behavior model and the rest of vehicles (say set B
) will use SUMO control;A
I will use traci.vehicle.moveToXY
to update their states. For vehicles in set B
I would like to keep SUMO's control.My observations and questions are:
traci.vehicle.setSpeed(vehID, -1)
(handle control back to SUMO) before traci.executeMove
to obtain a reasonable output from step2. For example, for a vehicle stop in front of a intersection and the signal light turns from red to green, the getSpeedWithoutTraci
will keep generating speed=0 if I did not add setSpeed(vehID, -1)
. Is that reasonable?setSpeed
), if I choose the control the vehicle and let it keep a standstill (using moveToXY
), I find that when I fetch the vehicle speed in the next timestep it follows the SUMO controlled speed (say 1.5m/s) rather than 0, although it did not move as shown in the GUI as I want. Moreover, in the next timestep, the output from getSpeedWithoutTraci
will keep increasing (for example 3m/s) as if the last step is controlled by SUMO, but I expect it to be 1.5m/s. Does that mean I need to manually patch the vehicle speed using setPreviousSpeed
when using executeMove
?Thanks for the help!
Hi @namdre, could you please take a look at this at your convenience? Thanks!
Basically, I want to get the speed which SUMO would issue to a certain vehicle in a simulation in the next time step, then pass this through an algorithm to obtain a calculated speed. This calculated speed will then be applied to the vehicle and
simulationStep()
is called.I looked at
traci.vehicle.getSpeedWithoutTraCI(veh_id)
, but this just returns the speed ifsetSpeed(veh_id, val)
during the last time step is ignored. E.g., ifsetSpeed(veh_id, 0)
andsimulationStep()
are called,traci.vehicle.getSpeedWithoutTraCI(veh_id)
always returns zero. So this does not really work for me.I know that I could use
getFollowSpeed
andgetStopSpeed
and then use the minimum of the two. However this does not take care of traffic lights or right-of-way-situations.Basically I need some method to return the speed which SUMO wants a certain vehicle to drive in the next time step. Is it possible to retrieve this value? It must be calculated within SUMO somewhere, right? If it is possible and does not exist at the moment, I would try to code that feature myself.