[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
| Re: [sumo-user] getSubscriptionResults in libtraci / C++ | 
  
  
    Hi Ruud, All,
    
    
    
    Thanks for the help. Calling the get*() in each step works. 
    
    
    
    Just to wrap up: the getSubscriptionResults() gives results that
      can be iterated for libtraci::Vehicle.
    It does not seem to provide any useable results for the
      libtraci::Simulation and libtraci::Edge though.
    
    
    
    Kind regards,
    Bart
    
    
    
    On 05-12-2023 17:45, Ruud van Gaal
      wrote:
    
    
      
      
        Hi
          Bart,
        
        
        I
          haven't really used arrival/departure a lot, since I have
          mostly flow vehicles. But at the beginning I used code like
          this, notably *outside* of the subscription results:
        
        
         
              int n=Simulation::getArrivedNumber();
                if(n>0) {
                  pt_Log("Query vehicles: arrivedNumber=%d",n);
            
                  auto id_list=Simulation::getArrivedIDList();
                  for(auto id:id_list) {
                    pt_Log("- %s",id.c_str());
                  }
                }
          
        
        
        Probably
          departure works exactly the same, but using
          getDepartedNumber() and getDepartedIDList().
        This
          has to be called after every simulation step. To avoid missing
          vehicles that arrive or depart, do call Simulation::step(0)
          instead of taking multiple steps (Simulation::step(new_time)).
          The getArrivedNumber() call only reports vehicles from
          the last simulation step. Also, when overruling properties of
          vehicles, you need to make sure you do this on every
          simulation step, and not take large jumps.
        
        
        As
          for keeping track of vehicle ID's, I keep a list of all
          vehicle ID's that I see in the subscription results. Then I
          remove and add vehicles as they disappear from the
          subscription results. This is slightly different from trying
          to keep a list of ALL vehicles in SUMO (which can be
          thousands); I only track the closest 50 or so within a radius.
        I
          guess for your case, keeping a local vehicle ID list and
          adding ID's as they are seen with 'getDepartedIDList()' and
          remove them when you see the ID in getArrivedIDList() is a
          nice way to keep an overview of all active vehicles within
          SUMO. There is a call to get them all, but the fewer calls to
          sumo-gui (over relatively slow TCP), the better.
        
        
        Cheers,
        Ruud
        
        
       
      
      
        
        
          
            HI Ruud,
            Yes i do subscribe during initialisation (before the
              first simulation step) for both VAR_DEPARTED_VEHICLES_IDS
              and VAR_ARRIVED_VEHICLES_IDS.
            Vehicle_ids seem to be generated by SUMO only during the
              simulation when a vehicle departs. So as soon as the above
              subscription gives a new vehicle id the vehicle
              subscription can be done. 
            Both subscriptions work fine. I can also receive and
              process subscription results for a specific vehicle, when
              i subscribe with a hard coded vehicle id. 
            
            The only thing i do not understand how to get the
              vehicle_id from the libtraci::Simulation subscription
              results. I expect some type of list or vector of vehicle
              ids in the subscription results, but 'r.second()->getString().c_str()'
              does not yield any vehicleid, or anything readable
              anyway.  
            Can you explain or give an example how to get every
              single vehicle id from the subscription results to
              VAR_DEPARTED_VEHICLES_IDS?
            Thanks a lot,
            Bart
            
            
            
            On 05-12-2023 17:09, Ruud van Gaal wrote:
            
            
              
                Hi Bart,
                
                
                Yes, all
                  subscribe results are returned in one batch. But that
                  is probably the better thing to do. Realise that all
                  these calls are really TCP send & receive calls to
                  'sumo-gui' or 'sumo'. So if you would intend to call
                  getSubscriptionResults() multiple times per simulation
                  step (each with a different filter), you're probably
                  reducing performance quite a bit.
                So it's
                  better to cache the results and make multiple passes
                  in your own code instead of calling expensive TraCI
                  functions.
                
                
                So
                  something like this would be much faster:
                
                
                void
                    ProcessSubResults()
                {
                  auto
                    sub_results =
                    Vehicle::getSubscriptionResults(name.c_str());
                  
                 
                    ProcessArrivedVehicles(sub_results);
                 
                    ProcessDepartedVehicles(sub_results);
                }
                  
                void
                    ProcessArrivedVehicles(...) {...}
                
                
                You
                  probably have something like this at subscription init
                  time already; do you request VAR_ARRIVED_VEHICLES_IDS
                  when subscribing?
                
                
                 
                    std::vector<int> vars;
                      // Info we need from vehicles in vicinity
                      vars.push_back(libsumo::VAR_SPEED);
                      vars.push_back(libsumo::VAR_ANGLE);
                      vars.push_back(libsumo::VAR_SLOPE);
                      vars.push_back(libsumo::VAR_SIGNALS);
                      vars.push_back(libsumo::VAR_POSITION3D);
                      Vehicle::subscribeContext(veh_id,
                    libsumo::CMD_GET_VEHICLE_VARIABLE,
                    prefSubscribeDistance, vars);
                  
                
                
                So, get
                  all sub results in one call (which is probably one TCP
                  send and receive call in the background), then do
                  processing on the batch of results in your own code
                  (where it's now local in memory).
                
                
                Indeed,
                  the variable id (int) is the first item of every pair.
                
                
                Cheers,
                Ruud
               
              
              
                
                
                  
                    Hi Ruud,
                    
                    
                    Thank you very much for the snippets. Very useful
                      for my next step to extract vehicle information.
                    As the first step i would like to get a list of
                      the vehicle ids that just departed from the
                      simulation (or newly arrived) to manage my
                      internal list of active vehicles. From your first
                      example it seems the results cannot be filtered to
                      only the VAR_ARRIVED_VEHICLES_IDS or VAR_DEPARTED_VEHICLES_IDS Instead all subscribed results are returned
                      in the sub_results map. The first element of the
                      map is the variable ID, correct? Then i would
                      expect the second element is a list of vehicle
                      ids:
                    
                       
                        auto sub_results =
                        Vehicle::getSubscriptionResults(name.c_str());
                            for (auto r : sub_results) {
                                int var_id = r.first();      
                      
                       
                            if (var_id ==
                        libsumo::VAR_ARRIVED_VEHICLES_IDS) {
                      
                       
                                char const* vehicle_ids =
                        r.second()->getString().c_str();
                       
                            }
                      
                        }
                      
                    However, the vehicle_ids string does seems to
                      contain any vehicle ids, list or ...
                    Is it possible to get just the list of vehicle
                      ids in the C++ lib (like in Python), and if so
                      how, or do i need to determine that from the
                      individual vehicles results like in your second
                      example?
                    
                    
                    Thanks,
                    Bart
                    
                    
                    
                    On 05-12-2023 10:12, Ruud van Gaal wrote:
                    
                    
                      
                        Hi Bart,
                        
                        
                        
                        Here are
                          some snippets. For getSubscriptionResults():
                        
                        
                           
                            auto sub_results =
                            Vehicle::getSubscriptionResults(name.c_str());
                                for (auto r : sub_results) {
                                  pt_LogDbg("- Ego subscr result type
                            0x%x: '%s'", r.first,
                            r.second->getString().c_str());
                                }
                          
                        
                        
                        I'm using
                          a context subscription really (only report
                          within a specific radius):
                        
                        
                         
                            libsumo::SubscriptionResults
                            subscriptionResults;
                              if (prefLogSumoCalls)
                                pt_Log("SUMO call:
                            Vehicle::getContextSubscriptionResults(%s)",
                            name.c_str());
                            
                              subscriptionResults =
                            Vehicle::getContextSubscriptionResults(name.c_str());
                            
                              // Go through results (parse)
                              std::string entity_id;
                              for (auto e : subscriptionResults) {
                                entity_id = e.first;
                                //pt_LogDbg("- Ego ctx subscr result
                            type '%s'", entity_id.c_str());
                            
                                auto res = e.second;
                                for (auto r : res) {
                                  //pt_LogDbg("  - subscr result var
                            0x%x value '%s''", r.first,
                            r.second->getString().c_str());
                                  switch (r.first) {
                                    case libsumo::VAR_ANGLE:
                                      vehicle->angle =
                            ParseDouble(r.second->getString());
                                      break;
                                    case libsumo::VAR_POSITION3D:
                             
                                 // Convert string to Vector3-like
                            struct
                                     
                            ParsePosition(r.second->getString(),
                            vehicle->position);
                                      break;
                                    case libsumo::VAR_TYPE:
                                      //pt_LogDbg("VAR_TYPE='%s'",
                            r.second->getString().c_str());
                                      vehicle->type_sumo =
                            r.second->getString();
                             
                                break;
                             
                              //////////////// etc
                                    default:
                                      pt_LogWarn("Var 0x%x is not
                            parsed; fix the source", r.first);
                                      break;
                                  }
                                }
                              }
                          
                        
                        
                        Hope that
                          helps,
                        Ruud
                        
                        
                        
                        
                       
                      
                      
                        
                        
                          
                            Dear
                                All,
                            
                              
                            Does
                              anyone have experience, or can send a link
                              to documentation, on how to process
                              results from a subscription in C++ using
                              libtraci? I need to convert the following
                              from Python into C++. The subscription is
                              for multiple types of variables. (not only
                            VAR_ARRIVED_VEHICLES_IDS). 
                            
                            
                            In
                                Python the implementation is rather
                                straightforward with the documentation
                                (e.g. in https://sumo.dlr.de/docs/TraCI/Interfacing_TraCI_from_Python.html).
                            
                            
                                  results = traci.simulation.getSubscriptionResults()
    for vehicle_id in results[tc.VAR_ARRIVED_VEHICLES_IDS]:
 	# process vehicle_id
This can be converted to C++ like this:
	libsumo::TraCIResults results = libtraci::Simulation::getSubscriptionResults();
	//std::map<int, std::shared_ptr<libsumo::TraCIResult> > libsumo::TraCIResults
	for (auto entry : results) {
		int i = entry.first;
		shared_ptr<libsumo::TraCIResult> result = entry.second;
How can the TraCIResults be filtered for ' libsumo::VAR_ARRIVED_VEHICLES_ID' values, and 
how to get the id values from the result?
Thanks  for the help,
Bart Netten
                             
                           
_______________________________________________
                          sumo-user mailing list
                          sumo-user@xxxxxxxxxxx
                          To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/sumo-user