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