real_robot.cpp
Go to the documentation of this file.
1 #include "real_robot.h"
2 #include <argos3/core/utility/rate.h>
3 #include <argos3/core/utility/logging/argos_log.h>
4 #include <argos3/core/control_interface/ci_controller.h>
5 #include <signal.h>
6 #include <unistd.h>
7 
8 using namespace argos;
9 
10 /****************************************/
11 /****************************************/
12 
14 
15 /****************************************/
16 /****************************************/
17 
19  m_pcController(NULL) {
20  /* Set instance */
21  m_pcInstance = this;
22 }
23 
24 /****************************************/
25 /****************************************/
26 
27 void CRealRobot::Init(const std::string& str_conf_fname,
28  const std::string& str_controller_id) {
29  /* Parse the .argos file */
30  m_tConfiguration.LoadFile(str_conf_fname);
31  m_tConfRoot = *m_tConfiguration.FirstChildElement();
32  /*
33  * Install signal handlers
34  */
35  ::signal(SIGINT, Cleanup);
36  ::signal(SIGQUIT, Cleanup);
37  ::signal(SIGABRT, Cleanup);
38  ::signal(SIGTERM, Cleanup);
39  /*
40  * Get the control rate
41  */
42  TConfigurationNode& tFramework = GetNode(m_tConfRoot, "framework");
43  TConfigurationNode& tExperiment = GetNode(tFramework, "experiment");
44  GetNodeAttribute(tExperiment, "ticks_per_second", m_fRate);
45  /*
46  * Parse XML to identify the controller to run
47  */
48  std::string strControllerId, strControllerTag;
49  TConfigurationNode& tControllers = GetNode(m_tConfRoot, "controllers");
50  TConfigurationNodeIterator itControllers;
51  /* Search for the controller tag with the given id */
52  for(itControllers = itControllers.begin(&tControllers);
53  itControllers != itControllers.end() && strControllerTag == "";
54  ++itControllers) {
55  GetNodeAttribute(*itControllers, "id", strControllerId);
56  if(strControllerId == str_controller_id) {
57  strControllerTag = itControllers->Value();
58  m_ptControllerConfRoot = &(*itControllers);
59  }
60  }
61  /* Make sure we found the tag */
62  if(strControllerTag == "") {
63  THROW_ARGOSEXCEPTION("Can't find controller with id \"" << str_controller_id << "\"");
64  }
65  /*
66  * Initialize the robot
67  */
68  LOG << "[INFO] Robot initialization start" << std::endl;
69  InitRobot();
70  LOG << "[INFO] Robot initialization done" << std::endl;
71  /*
72  * Initialize the controller
73  */
74  LOG << "[INFO] Controller type '" << strControllerTag << "', id '" << str_controller_id << "' initialization start" << std::endl;
75 #ifdef ARGOS_DYNAMIC_LIBRARY_LOADING
77 #else
78  m_pcController = ControllerMaker(strControllerTag);
79 #endif
80  /* Set the controller id using the machine hostname */
81  char pchHostname[256];
82  pchHostname[255] = '\0';
83  ::gethostname(pchHostname, 255);
84  m_pcController->SetId(pchHostname);
85  LOG << "[INFO] Controller id set to '" << pchHostname << "'" << std::endl;
86  /* Go through actuators */
87  TConfigurationNode& tActuators = GetNode(*m_ptControllerConfRoot, "actuators");
89  for(itAct = itAct.begin(&tActuators);
90  itAct != itAct.end();
91  ++itAct) {
92  /* itAct->Value() is the name of the current actuator */
93  CCI_Actuator* pcCIAct = MakeActuator(itAct->Value());
94  if(pcCIAct == NULL) {
95  THROW_ARGOSEXCEPTION("Unknown actuator \"" << itAct->Value() << "\"");
96  }
97  pcCIAct->Init(*itAct);
98  m_pcController->AddActuator(itAct->Value(), pcCIAct);
99  }
100  /* Go through sensors */
101  TConfigurationNode& tSensors = GetNode(*m_ptControllerConfRoot, "sensors");
103  for(itSens = itSens.begin(&tSensors);
104  itSens != itSens.end();
105  ++itSens) {
106  /* itSens->Value() is the name of the current sensor */
107  CCI_Sensor* pcCISens = MakeSensor(itSens->Value());
108  if(pcCISens == NULL) {
109  THROW_ARGOSEXCEPTION("Unknown sensor \"" << itSens->Value() << "\"");
110  }
111  pcCISens->Init(*itSens);
112  m_pcController->AddSensor(itSens->Value(), pcCISens);
113  }
114  /* Configure the controller */
116  LOG << "[INFO] Controller type '" << strControllerTag << "', id '" << str_controller_id << "' initialization done" << std::endl;
117 }
118 
119 /****************************************/
120 /****************************************/
121 
123  if(m_pcController)
124  delete m_pcController;
125 }
126 
127 /****************************************/
128 /****************************************/
129 
132 }
133 
134 /****************************************/
135 /****************************************/
136 
138  /* Enforce the control rate */
139  CRate cRate(m_fRate);
140  /* Main loop */
141  LOG << "[INFO] Control loop running" << std::endl;
142  /* Save current time */
143  ::timeval tPast, tNow, tDiff;
144  Real fElapsed;
145  ::gettimeofday(&tPast, NULL);
146  while(1) {
147  /* Get elapsed time */
148  ::gettimeofday(&tNow, NULL);
149  timersub(&tNow, &tPast, &tDiff);
150  fElapsed = static_cast<Real>(tDiff.tv_sec * 1000000 + tDiff.tv_usec) / 1e6;
151  tPast = tNow;
152  /* Do useful work */
153  Sense(fElapsed);
154  Control();
155  Act(fElapsed);
156  /* Sleep to enforce control rate */
157  cRate.Sleep();
158  }
159 }
160 
161 /****************************************/
162 /****************************************/
163 
165  LOG << "[INFO] Stopping controller" << std::endl;
166  if(m_pcInstance != NULL) {
168  delete m_pcInstance;
169  }
170  LOG << "[INFO] All done" << std::endl;
171  exit(0);
172 }
173 
174 /****************************************/
175 /****************************************/
argos::CCI_Controller * ControllerMaker(const std::string &str_label)
Registers a new controller inside ARGoS.
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
float Real
Collects all ARGoS code.
Definition: datatypes.h:39
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
ticpp::Iterator< ticpp::Element > TConfigurationNodeIterator
The iterator for the ARGoS configuration XML node.
TConfigurationNode & GetNode(TConfigurationNode &t_node, const std::string &str_tag)
Given a tree root node, returns the first of its child nodes with the wanted name.
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
CARGoSLog LOG(std::cout, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_GREEN))
Definition: argos_log.h:179
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
The basic interface for all actuators.
Definition: ci_actuator.h:34
virtual void Init(TConfigurationNode &t_node)
Initializes the actuator from the XML configuration tree.
Definition: ci_actuator.h:54
virtual void Init(TConfigurationNode &t_node)
Initializes the controller.
Definition: ci_controller.h:48
void AddSensor(const std::string &str_sensor_type, CCI_Sensor *pc_sensor)
Adds an sensor to this controller.
virtual void ControlStep()
Executes a control step.
Definition: ci_controller.h:55
void SetId(const std::string &str_id)
Sets the id of the robot associated to this controller.
Definition: ci_controller.h:88
void AddActuator(const std::string &str_actuator_type, CCI_Actuator *pc_actuator)
Adds an actuator to this controller.
The basic interface for all sensors.
Definition: ci_sensor.h:34
virtual void Init(TConfigurationNode &t_node)
Initializes the sensor from the XML configuration tree.
Definition: ci_sensor.h:54
virtual void Init(const std::string &str_conf_fname, const std::string &str_controller_id)
Initializes the robot and the controller.
Definition: real_robot.cpp:27
virtual void Control()
Execute the robot controller.
Definition: real_robot.cpp:130
virtual ~CRealRobot()
Class destructor.
Definition: real_robot.cpp:122
virtual void Destroy()=0
Put your robot cleanup code here.
CCI_Controller * m_pcController
Definition: real_robot.h:79
ticpp::Document m_tConfiguration
Definition: real_robot.h:80
TConfigurationNode * m_ptControllerConfRoot
Definition: real_robot.h:82
virtual void Act(Real f_elapsed_time)=0
Send data to the actuators.
CRealRobot()
Class constructor.
Definition: real_robot.cpp:18
TConfigurationNode m_tConfRoot
Definition: real_robot.h:81
virtual void Execute()
Performs the main loop.
Definition: real_robot.cpp:137
virtual CCI_Actuator * MakeActuator(const std::string &str_name)=0
Creates an actuator given its name.
virtual void Sense(Real f_elapsed_time)=0
Collect data from the sensors.
static void Cleanup(int)
Cleanup function called when the controller is stopped.
Definition: real_robot.cpp:164
virtual CCI_Sensor * MakeSensor(const std::string &str_name)=0
Creates a sensor given its name.
virtual void InitRobot()=0
Put your robot initialization code here.
static CRealRobot * m_pcInstance
Definition: real_robot.h:84
static TYPE * New(const std::string &str_label)
Creates a new object of type TYPE
Definition: factory_impl.h:48
void Sleep()
Sleeps for the appropriate time to complete the period.
Definition: rate.cpp:38