ARGoS 3
A parallel, multi-engine simulator for swarm robotics
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
15namespace 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
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 */
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 }
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}
signed int SInt32
32-bit signed integer.
Definition datatypes.h:93
#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.
#define REGISTER_CONTROLLER(CLASSNAME, LABEL)
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.
const std::string & GetId() const
Returns the id of the robot associated to this controller.
CCI_Sensor::TMap m_mapSensors
A map containing all the sensors associated to this controller.
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)
static void RegisterType(lua_State *pt_state)