lua_controller.cpp
Go to the documentation of this file.
1 
7 #include "lua_controller.h"
8 #include <argos3/core/utility/logging/argos_log.h>
9 
10 #include <argos3/core/wrappers/lua/lua_utility.h>
11 
12 namespace argos {
13 
14  /****************************************/
15  /****************************************/
16 
18  m_ptLuaState(NULL),
19  m_bScriptActive(false),
20  m_bIsOK(true),
21  m_pcRNG(NULL) {
22  }
23 
24  /****************************************/
25  /****************************************/
26 
28  }
29 
30  /****************************************/
31  /****************************************/
32 
34  try {
35  /* Create RNG */
36  m_pcRNG = CRandom::CreateRNG("argos");
37  /* Load script */
38  std::string strScriptFileName;
39  GetNodeAttributeOrDefault(t_tree, "script", strScriptFileName, strScriptFileName);
40  if(strScriptFileName != "") {
41  SetLuaScript(strScriptFileName, t_tree);
42  if(! m_bIsOK) {
43  THROW_ARGOSEXCEPTION("Error loading Lua script \"" << strScriptFileName << "\": " << lua_tostring(m_ptLuaState, -1));
44  }
45  }
46  else {
47  /* Create a new Lua stack */
48  m_ptLuaState = luaL_newstate();
49  /* Load the Lua libraries */
50  luaL_openlibs(m_ptLuaState);
51  /* Create and set Lua state */
54  }
55  }
56  catch(CARGoSException& ex) {
57  THROW_ARGOSEXCEPTION_NESTED("Error initializing Lua controller", ex);
58  }
59  }
60 
61  /****************************************/
62  /****************************************/
63 
65  if(m_bScriptActive && m_bIsOK) {
66  /* Update Lua state through sensor readings */
68  /* Execute script step function */
69  if(! CLuaUtility::CallLuaFunction(m_ptLuaState, "step")) {
70  m_bIsOK = false;
71  }
72  }
73  }
74 
75  /****************************************/
76  /****************************************/
77 
79  if(m_bScriptActive) {
80  if(m_bIsOK) {
81  m_bIsOK = CLuaUtility::CallLuaFunction(m_ptLuaState, "reset");
82  }
83  else {
84  SetLuaScript(m_strScriptFileName);
85  }
86  }
87  }
88 
89  /****************************************/
90  /****************************************/
91 
93  if(m_bScriptActive && m_bIsOK) {
94  /* Execute script destroy function */
95  CLuaUtility::CallLuaFunction(m_ptLuaState, "destroy");
96  }
97  /* Close Lua */
98  lua_close(m_ptLuaState);
99  }
100 
101  /****************************************/
102  /****************************************/
103 
104  void CLuaController::SetLuaScript(const std::string& str_script,
105  TConfigurationNode& t_tree) {
106  /* First, delete old script */
107  if(m_bScriptActive) {
108  lua_close(m_ptLuaState);
109  m_bScriptActive = false;
110  m_strScriptFileName = "";
111  }
112  /* Create a new Lua stack */
113  m_ptLuaState = luaL_newstate();
114  /* Load the Lua libraries */
115  luaL_openlibs(m_ptLuaState);
116  /* Load script */
117  if(!CLuaUtility::LoadScript(m_ptLuaState, str_script)) {
118  m_bIsOK = false;
119  return;
120  }
121  m_strScriptFileName = str_script;
122  /* Create and set variables */
123  CreateLuaState();
125  ParametersToLuaState(t_tree);
126  /* Execute script init function */
127  if(!CLuaUtility::CallLuaFunction(m_ptLuaState, "init")) {
128  m_bIsOK = false;
129  return;
130  }
131  m_bIsOK = true;
132  m_bScriptActive = true;
133  }
134 
135  /****************************************/
136  /****************************************/
137 
138  void CLuaController::SetLuaScript(const std::string& str_script) {
139  TConfigurationNode t_tree;
140  SetLuaScript(str_script, t_tree);
141  }
142 
143  /****************************************/
144  /****************************************/
145 
147  /* Register functions */
149  /* Create a table that will contain the state of the robot */
150  lua_newtable(m_ptLuaState);
151  /* Set the id of the robot */
152  lua_pushstring(m_ptLuaState, "id");
153  lua_pushstring(m_ptLuaState, GetId().c_str());
154  lua_settable(m_ptLuaState, -3);
155  /* Register RNG */
156  CLuaUtility::RegisterRNG(m_ptLuaState, m_pcRNG);
157  /* Go through devices and add the necessary items to the table */
158  for(CCI_Actuator::TMap::iterator it = m_mapActuators.begin();
159  it != m_mapActuators.end();
160  ++it) {
161  it->second->CreateLuaState(m_ptLuaState);
162  }
163  for(CCI_Sensor::TMap::iterator it = m_mapSensors.begin();
164  it != m_mapSensors.end();
165  ++it) {
166  it->second->CreateLuaState(m_ptLuaState);
167  }
168  /* Set the name of the table */
169  lua_setglobal(m_ptLuaState, "robot");
170  }
171 
172  /****************************************/
173  /****************************************/
174 
176  /* Put the robot state table on top */
177  lua_getglobal(m_ptLuaState, "robot");
178  /* Go through the sensors */
179  for(CCI_Sensor::TMap::iterator it = m_mapSensors.begin();
180  it != m_mapSensors.end();
181  ++it) {
182  it->second->ReadingsToLuaState(m_ptLuaState);
183  }
184  /* Pop the robot state table */
185  lua_pop(m_ptLuaState, 1);
186  }
187 
188  /****************************************/
189  /****************************************/
190 
192  /* Put the robot state table on top */
193  lua_getglobal(m_ptLuaState, "robot");
194  /* Add a table for the XML params to the global symbol table and fill it with values */
195  CLuaUtility::OpenRobotStateTable(m_ptLuaState, "params");
197  std::string strKey;
198  std::string strValue;
199  for (it = it.begin(&t_tree); it != it.end(); ++it) {
200  it.Get()->GetName(&strKey);
201  it.Get()->GetValue(&strValue);
202  CLuaUtility::AddToTable(m_ptLuaState, strKey, strValue);
203  }
204  CLuaUtility::CloseRobotStateTable(m_ptLuaState);
205  /* Pop the robot state table */
206  lua_pop(m_ptLuaState, 1);
207  }
208 
209  /****************************************/
210  /****************************************/
211 
213  if(m_bIsOK) {
214  return "OK";
215  }
216  else {
217  SInt32 i = 1;
218  while(i <= lua_gettop(m_ptLuaState) && lua_type(m_ptLuaState, i) != LUA_TSTRING) {
219  CLuaUtility::PrintStack(LOGERR, m_ptLuaState);
220  ++i;
221  }
222  if(i > lua_gettop(m_ptLuaState)) return "Unknown compilation error";
223  else return lua_tostring(m_ptLuaState, i);
224  }
225  }
226 
227  /****************************************/
228  /****************************************/
229 
230  REGISTER_CONTROLLER(CLuaController, "lua_controller");
231 
232 }
virtual void ParametersToLuaState(TConfigurationNode &t_tree)
CCI_Sensor::TMap m_mapSensors
A map containing all the sensors associated to this controller.
static void AddToTable(lua_State *pt_state, const std::string &str_key, void *pt_data)
Adds a pointer to a chunk of data with the given string key to the table located at the top of the st...
signed int SInt32
32-bit signed integer.
Definition: datatypes.h:93
virtual void Reset()
Resets the state of the controller to what it was right after Init() was executed.
void GetNodeAttributeOrDefault(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer, const T &t_default)
Returns the value of a node's attribute, or the passed default value.
virtual void SensorReadingsToLuaState()
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
static void RegisterRNG(lua_State *pt_state, CRandom::CRNG *pc_rng)
Registers the given random number generator in the Lua state.
static bool LoadScript(lua_State *pt_state, const std::string &str_filename)
Loads the given Lua script.
static bool CallLuaFunction(lua_State *pt_state, const std::string &str_function)
Calls a parameter-less function in the Lua script.
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception...
virtual void Init(TConfigurationNode &t_tree)
Initializes the controller.
std::string GetErrorMessage()
virtual void Destroy()
The default implementation of this method does nothing.
const std::string & GetId() const
Returns the id of the robot associated to this controller.
Definition: ci_controller.h:78
virtual void ControlStep()
Executes a control step.
ticpp::Iterator< ticpp::Attribute > TConfigurationAttributeIterator
The iterator for the attributes of an XML node.
static void PrintStack(CARGoSLog &c_log, lua_State *pt_state)
Prints the Lua stack on the specified log.
CCI_Actuator::TMap m_mapActuators
A map containing all the actuators associated to this controller.
CARGoSLog LOGERR(std::cerr, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_RED))
Definition: argos_log.h:180
The exception that wraps all errors in ARGoS.
static void RegisterLoggerWrapper(lua_State *pt_state)
Registers LOG and LOGERR in the Lua state.
virtual void CreateLuaState()
static CRNG * CreateRNG(const std::string &str_category)
Creates a new RNG inside the given category.
Definition: rng.cpp:326
static void OpenRobotStateTable(lua_State *pt_state, const std::string &str_key)
Opens a table in the robot state, creating it if it does not exist.
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
static void CloseRobotStateTable(lua_State *pt_state)
Closes a table in the robot state.
REGISTER_CONTROLLER(CLuaController,"lua_controller")
virtual void SetLuaScript(const std::string &str_script, TConfigurationNode &t_tree)