diff --git a/src/tools/visualStates_py/.idea/inspectionProfiles/profiles_settings.xml b/src/tools/visualStates_py/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..c23ecacb3 --- /dev/null +++ b/src/tools/visualStates_py/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/src/tools/visualStates_py/.idea/misc.xml b/src/tools/visualStates_py/.idea/misc.xml new file mode 100644 index 000000000..5bbe586f1 --- /dev/null +++ b/src/tools/visualStates_py/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/tools/visualStates_py/.idea/modules.xml b/src/tools/visualStates_py/.idea/modules.xml new file mode 100644 index 000000000..f34e1f1dc --- /dev/null +++ b/src/tools/visualStates_py/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/tools/visualStates_py/.idea/visualStates_py.iml b/src/tools/visualStates_py/.idea/visualStates_py.iml new file mode 100644 index 000000000..3f8acbf35 --- /dev/null +++ b/src/tools/visualStates_py/.idea/visualStates_py.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/tools/visualStates_py/.idea/workspace.xml b/src/tools/visualStates_py/.idea/workspace.xml new file mode 100644 index 000000000..578bbc8d4 --- /dev/null +++ b/src/tools/visualStates_py/.idea/workspace.xml @@ -0,0 +1,1124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + copyRuntime + self.configs + State + Transition + State.__i + generateInterfaces + comm.ini + #include + destroy + cmake + std::cout + cout + print + print( + print(' + print('t + print('type + interface + interfaceHeaders + package + getFunction + functions + signal + varName[0] + parseFunctions + getVar + runCode + doc.create + getVariables + replace + + + + Okan Asik + + + $PROJECT_DIR$ + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + project + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1499771568074 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/tools/visualStates_py/codegen/cpp/runtimegui.cpp b/src/tools/visualStates_py/codegen/cpp/runtimegui.cpp index eeae45a97..e6942d4fa 100644 --- a/src/tools/visualStates_py/codegen/cpp/runtimegui.cpp +++ b/src/tools/visualStates_py/codegen/cpp/runtimegui.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,14 +29,14 @@ RunTimeGui::RunTimeGui() { // create shared memory - createSharedMem(); + createSharedMemAndSemaphore(); pthread_create(&threadIPC, NULL, &RunTimeGui::loopStaticIPC, this); - ipcData[0] == '0'; + } void RunTimeGui::emitRunningStateById(int id) { std::stringstream strstream; - strstream << "emitRunningStateById " << id; + strstream << "emitRunningStateById " << id << " "; msgQueue.push(strstream.str()); // std::cout << "running state:" << id << std::endl; } @@ -43,13 +44,13 @@ void RunTimeGui::emitRunningStateById(int id) { void RunTimeGui::emitLoadFromRoot() { std::stringstream strstream; // strstream << "emitLoadFromRoot"; - msgQueue.push(strstream.str()); +// msgQueue.push(strstream.str()); } void RunTimeGui::emitActiveStateById(int id) { std::stringstream strstream; // strstream << "emitActiveStateById " << id; - msgQueue.push(strstream.str()); +// msgQueue.push(strstream.str()); } void* RunTimeGui::loopStaticIPC(void* owner) { @@ -57,24 +58,34 @@ void* RunTimeGui::loopStaticIPC(void* owner) { } void RunTimeGui::loopIPC() { + struct sembuf sb = {0, 0, 0}; /* set to allocate resource */ + int semop_result; while(true) { +// std::cout <<"data:"<< std::endl; +// for (int i = 0; i < 1024; i++) { +// std::cout << ipcData[i]; +// } +// std::cout << ":data" << std::endl; +// std::cout << "msg.size=" << msgQueue.size() << std::endl; if (msgQueue.size() > 0) { - if (ipcData[0] == '0') { - std::string msg = msgQueue.front(); - msgQueue.pop(); - strncpy(ipcData, msg.c_str(), 1024); - } + sb.sem_op = 0; + semop_result = semop(sem_id, &sb, 1); + std::string msg = msgQueue.front(); + std::cout << "sending msg:" << msg << std::endl; + msgQueue.pop(); + strncpy(ipcData, msg.c_str(), 1024); + sb.sem_op = 1; + semop_result = semop(sem_id, &sb, 1); } - - usleep(1000); +// usleep(1000); } } -void RunTimeGui::createSharedMem() { +void RunTimeGui::createSharedMemAndSemaphore() { key_t fkey; int shmid; int mode; - int numTrial = 15; + int numTrial = 10; int trial = 0; while (trial < numTrial) { @@ -83,6 +94,7 @@ void RunTimeGui::createSharedMem() { } else { break; } + trial++; usleep(100000); // sleep for 100 milliseconds } @@ -94,9 +106,23 @@ void RunTimeGui::createSharedMem() { return; } + trial = 0; + while (trial < numTrial) { + if ((sem_id = semget(9, 1, 0)) == -1) { + std::cerr << "semget error with id 9 try for " << trial << std::endl; + } else { + break; + } + + trial++; + usleep(100000); // sleep for 100 milliseconds + } + ipcData = (char*) shmat(shmid, (void *)0, 0); if (ipcData == (char *)(-1)) { std::cerr << "error shmat" << std::endl; return; } + + } diff --git a/src/tools/visualStates_py/codegen/cpp/runtimegui.h b/src/tools/visualStates_py/codegen/cpp/runtimegui.h index c17fe9519..752cdb9de 100644 --- a/src/tools/visualStates_py/codegen/cpp/runtimegui.h +++ b/src/tools/visualStates_py/codegen/cpp/runtimegui.h @@ -27,10 +27,11 @@ class RunTimeGui { protected: pthread_t threadIPC; + int sem_id; std::queue msgQueue; char* ipcData; - void createSharedMem(); + void createSharedMemAndSemaphore(); public: RunTimeGui(); diff --git a/src/tools/visualStates_py/codegen/cpp/temporaltransition.cpp b/src/tools/visualStates_py/codegen/cpp/temporaltransition.cpp index 29963a58e..3adad6f3a 100644 --- a/src/tools/visualStates_py/codegen/cpp/temporaltransition.cpp +++ b/src/tools/visualStates_py/codegen/cpp/temporaltransition.cpp @@ -20,7 +20,8 @@ #include "temporaltransition.h" #include -TemporalTransition::TemporalTransition(int id, int destinationId, int elapsedTime):Transition(id, destinationId) { +TemporalTransition::TemporalTransition(int id, int destinationId, int elapsedTime): + Transition(id, destinationId) { this->elapsedTime = elapsedTime; } diff --git a/src/tools/visualStates_py/codegen/cpp/transition.h b/src/tools/visualStates_py/codegen/cpp/transition.h index 94263b92a..6dac678ce 100644 --- a/src/tools/visualStates_py/codegen/cpp/transition.h +++ b/src/tools/visualStates_py/codegen/cpp/transition.h @@ -20,6 +20,8 @@ #ifndef TRANSITION_H #define TRANSITION_H +class State; + class Transition { protected: int id; diff --git a/src/tools/visualStates_py/codegen/python/runtimegui.py b/src/tools/visualStates_py/codegen/python/runtimegui.py index 5cb494727..481a33719 100644 --- a/src/tools/visualStates_py/codegen/python/runtimegui.py +++ b/src/tools/visualStates_py/codegen/python/runtimegui.py @@ -64,6 +64,7 @@ def __init__(self, parent=None): self.memory = None self.ipcThread = None + self.semaphore = None def createTreeView(self): dockWidget = QDockWidget() @@ -209,37 +210,40 @@ def getStateList(self, state, stateList): def loopIPC(self): while True: msg = self.getIPCMessage() - if msg is not None and len(msg) > 0: - methodName = msg.split(' ')[0] - id = int(msg.split(' ')[1]) - if methodName == 'emitRunningStateById': - self.emitRunningStateById(id) - else: - print('unknown method name') - - time.sleep(1.0/1000) + if msg is not None: + if len(msg) > 0: + msg = msg.strip() + methodName = msg.split(' ')[0] + id = int(msg.split(' ')[1]) + if methodName == 'emitRunningStateById': + self.emitRunningStateById(id) + else: + print('unknown method name') + + # time.sleep(1.0/1000) def activateIPC(self): try: - self.memory = sysv_ipc.SharedMemory(123456, sysv_ipc.IPC_CREX) + self.memory = sysv_ipc.SharedMemory(123456, flags=sysv_ipc.IPC_CREAT, size = 1024) + except: + print('cannot create or open share mem with id 123456') + return + + # create sempahore + try: + self.semaphore = sysv_ipc.Semaphore(9, flags=sysv_ipc.IPC_CREAT, initial_value=0) except: - # if memory exists just open shared memory - self.memory = sysv_ipc.SharedMemory(123456) + print('cannot create or open semaphore with id 9') + self.memory.remove() + return self.ipcThread = Thread(target=self.loopIPC) self.ipcThread.start() def getIPCMessage(self): - if self.memory is not None: - data = self.memory.read().decode() - if data[0] != '0': - self.memory.write('0'.encode()) - i = data.find('\0') - if i != -1: - data = data[:i] - return data - - return None + self.semaphore.acquire() + data = self.memory.read().decode() + return data diff --git a/src/tools/visualStates_py/codegen/python/temporaltransition.py b/src/tools/visualStates_py/codegen/python/temporaltransition.py index 0f3ad0b93..6aed45360 100644 --- a/src/tools/visualStates_py/codegen/python/temporaltransition.py +++ b/src/tools/visualStates_py/codegen/python/temporaltransition.py @@ -20,8 +20,8 @@ from codegen.python.transition import Transition from time import time -class TemporalTransition(Transition, object): - def __init__(self, id, destinationId, elapsedTime): +class TemporalTransition(Transition): + def __init__(self, id, destinationId, elapsedTime): super(TemporalTransition, self).__init__(id, destinationId) # elapsed time in milliseconds self.elapsedTime = elapsedTime diff --git a/src/tools/visualStates_py/cpptest b/src/tools/visualStates_py/cpptest new file mode 100755 index 000000000..f8412c220 Binary files /dev/null and b/src/tools/visualStates_py/cpptest differ diff --git a/src/tools/visualStates_py/gui/cppgenerator.py b/src/tools/visualStates_py/gui/cppgenerator.py index 87adaf7cd..5e46655ff 100644 --- a/src/tools/visualStates_py/gui/cppgenerator.py +++ b/src/tools/visualStates_py/gui/cppgenerator.py @@ -66,7 +66,7 @@ def getAllTransitions(self): def generate(self, projectPath, projectName): stringList = [] self.generateHeaders(stringList, projectName) - self.generateInterfaceClasses(stringList) + self.generateInterfaceClass(stringList) self.generateStateClasses(stringList) self.generateTransitionClasses(stringList) stringList.append('#endif') @@ -79,7 +79,7 @@ def generate(self, projectPath, projectName): self.generateHeadersForCpp(stringList, projectName) self.generateStateMethods(stringList) self.generateTranMethods(stringList) - self.generateProxies(stringList, projectName) + self.generateInterfaceMethods(stringList, projectName) self.generateReadArgs(stringList, projectName) self.generateMain(stringList, projectName) sourceCode = ''.join(stringList) @@ -143,17 +143,12 @@ def generateStateClasses(self, classStr): classStr.append('class State' + str(state.id) + ' : public State {\n') classStr.append('public:\n') classStr.append('\tInterfaces* interfaces;\n') - classStr.append(state.getVariables()) classStr.append('\tState' + str(state.id) + '(int id, bool initial, Interfaces* interfaces, int cycleDuration, State* parent, RunTimeGui* gui):\n') classStr.append('\t\tState(id, initial, cycleDuration, parent, gui) {this->interfaces = interfaces;}\n') classStr.append('\tvirtual void runCode();\n') - - returnTypes, funcNames, codes = CPPParser.parseFunctions(state.getFunctions()) - for i in range(len(returnTypes)): - classStr.append('\t' + returnTypes[i] + ' ' + funcNames[i] + ';\n') - classStr.append('};\n\n') + def generateTransitionClasses(self, classStr): for tran in self.getAllTransitions(): if tran.getType() == TransitionType.CONDITIONAL: @@ -169,11 +164,13 @@ def generateTransitionClasses(self, classStr): elif tran.getType() == TransitionType.TEMPORAL: classStr.append('class Tran' + str(tran.id) + ' : public TemporalTransition {\n') classStr.append('\tpublic:\n') - classStr.append('\tTran' + str(tran.id) + '(int id, int destId, int elapsedTime):TemporalTransition(id, destId, elapsedTime) {}\n') + classStr.append('\tTran' + str(tran.id) + '(int id, int destId, int elapsedTime):\n') + classStr.append('TemporalTransition(id, destId, elapsedTime) {}\n') classStr.append('\tvirtual void runCode();\n') classStr.append('};\n\n') - def generateInterfaceClasses(self, classStr): + + def generateInterfaceClass(self, classStr): classStr.append('class Interfaces {\n') classStr.append('public:\n') classStr.append('\tComm::Communicator* jdrc;\n') @@ -182,8 +179,18 @@ def generateInterfaceClasses(self, classStr): classStr.append('\n') classStr.append('\tvirtual void connectProxies(int argc, char* argv[]);\n') classStr.append('\tvirtual void destroyProxies();\n') + for state in self.getAllStates(): + # define variables + types, varNames, initialValues = CPPParser.parseVariables(state.getVariables()) + for i in range(len(types)): + classStr.append('\t' + types[i] + ' ' + varNames[i] + ';\n') + classStr.append('\n') + returnTypes, funcNames, codes = CPPParser.parseFunctions(state.getFunctions()) + for i in range(len(returnTypes)): + classStr.append('\t' + returnTypes[i] + ' ' + funcNames[i] + ';\n') classStr.append('};\n\n') + def generateHeadersForCpp(self, headerStr, projectName): headerStr.append('#include "' + projectName + '.h"\n') headerStr.append('#include \n') @@ -197,11 +204,6 @@ def generateStateMethods(self, stateStr): stateStr.append('\t' + codeLine + '\n') stateStr.append('}\n\n') - returnTypes, funcNames, codes = CPPParser.parseFunctions(state.getFunctions()) - for i in range(len(returnTypes)): - stateStr.append(returnTypes[i] + ' State' + str(state.id) + '::' + funcNames[i] + '\n') - stateStr.append(codes[i]) - stateStr.append('\n\n') def generateTranMethods(self, tranStr): for tran in self.getAllTransitions(): @@ -209,7 +211,7 @@ def generateTranMethods(self, tranStr): #todo: currently user does not provide init method tranStr.append('void Tran' + str(tran.id) + '::init() {\n') tranStr.append('}\n\n') - tranStr.append('void Tran' + str(tran.id) + '::checkCondition() {\n') + tranStr.append('bool Tran' + str(tran.id) + '::checkCondition() {\n') for codeLine in tran.getCondition().split('\n'): tranStr.append('\t' + codeLine + '\n') tranStr.append('}\n') @@ -220,7 +222,7 @@ def generateTranMethods(self, tranStr): tranStr.append('}\n\n') - def generateProxies(self, proxyStr, projectName): + def generateInterfaceMethods(self, proxyStr, projectName): proxyStr.append('void Interfaces::connectProxies(int argc, char* argv[]) {\n') proxyStr.append('\tConfig::Properties props = Config::load(argc, argv);\n') proxyStr.append('\tjdrc = new Comm::Communicator(props);\n\n') @@ -229,13 +231,29 @@ def generateProxies(self, proxyStr, projectName): proxyStr.append('\tif (' + cfg['name'] + ' == NULL) {\n') proxyStr.append('\t\tthrow "invalid proxy ' + cfg['name'] + '";\n') proxyStr.append('\t}\n') - proxyStr.append('\tstd::cout << "' + cfg['name'] + ' is connected" << std::endl;\n') + proxyStr.append('\tstd::cout << "' + cfg['name'] + ' is connected" << std::endl;\n\n') + + # set inital values of variables + for state in self.getAllStates(): + types, varNames, initialValues = CPPParser.parseVariables(state.getVariables()) + for i in range(len(types)): + if initialValues[i] is not None: + proxyStr.append('\t' + varNames[i] + ' = ' + initialValues[i] + ';\n') + proxyStr.append('}\n\n') proxyStr.append('void Interfaces::destroyProxies() {\n') proxyStr.append('\tif (jdrc != 0) {\n') proxyStr.append('\t}\n}\n\n') + for state in self.getAllStates(): + returnTypes, funcNames, codes = CPPParser.parseFunctions(state.getFunctions()) + for i in range(len(returnTypes)): + proxyStr.append(returnTypes[i] + ' Interfaces::' + funcNames[i] + '\n') + proxyStr.append(codes[i]) + proxyStr.append('\n\n') + + def generateReadArgs(self, argStr, projectName): mystr = ''' pthread_t guiThread; @@ -308,11 +326,11 @@ def generateMain(self, mainStr, projectName): # create transition instances for tran in self.getAllTransitions(): if tran.getType() == TransitionType.CONDITIONAL: - mainStr.append('\tTransition* tran' + str(tran.id) + ' = new Tran' + str(tran.id) + '(' + str(tran.id) + - ', ' + str(tran.destination.id) + ', &interfaces);\n') + mainStr.append('\tTransition* tran' + str(tran.id) + ' = new Tran' + str(tran.id) + + '(' + str(tran.id) + ', ' + str(tran.destination.id) + ', &interfaces);\n') elif tran.getType() == TransitionType.TEMPORAL: - mainStr.append('\tTransition* tran' + str(tran.id) + ' = new Tran' + str(tran.id) + '(' + str(tran.id) + - ', ' + str(tran.destination.id) + ', ' + str(tran.getTemporalTime()) + ');\n') + mainStr.append('\tTransition* tran' + str(tran.id) + ' = new Tran' + str(tran.id) + + '(' + str(tran.id) + ', ' + str(tran.destination.id) + ', ' + str(tran.getTemporalTime()) + ');\n') mainStr.append('\tstate' + str(tran.origin.id) + '->addTransition(tran' + str(tran.id) + ');\n') mainStr.append('\n') diff --git a/src/tools/visualStates_py/gui/cppparser.py b/src/tools/visualStates_py/gui/cppparser.py index 90fd395f4..f3c20f302 100644 --- a/src/tools/visualStates_py/gui/cppparser.py +++ b/src/tools/visualStates_py/gui/cppparser.py @@ -42,11 +42,11 @@ def parseFunctions(funcStr): firstCurlyIndex = None lastCurlyIndex = None for i, ch in enumerate(funcStr): - if ch == '{': curlyCounter += 1 - firstCurlyFound = True - firstCurlyIndex = i + if not firstCurlyFound: + firstCurlyFound = True + firstCurlyIndex = i elif ch == '}': curlyCounter -= 1 @@ -70,6 +70,34 @@ def parseFunctions(funcStr): return returnTypes, funcNames, codes + @staticmethod + def parseVariables(variableStr): + types = [] + varNames = [] + initialValues = [] + variableStr = variableStr.strip() + variableLines = variableStr.split(';') + for varLine in variableLines: + varLine = varLine.strip() + if len(varLine) == 0: + continue + + varType = varLine[0:varLine.find(' ')] + varName = None + initalValue = None + if varLine.find('=') >= 0: + # if there is initial value + varName = varLine[varLine.find(' ')+1:varLine.find('=')].strip() + initialValue = varLine[varLine.find('=')+1:].strip() + else: + varName = varLine[varLine.find(' ')+1:].strip() + + types.append(varType) + varNames.append(varName) + initialValues.append(initialValue) + + return types, varNames, initialValues + if __name__ == '__main__': sampleCode = ''' @@ -83,6 +111,9 @@ def parseFunctions(funcStr): c = 10; d = 12; a = c*d*b; + if ( a == 2) { + b = 3; + } return a; } @@ -93,12 +124,27 @@ def parseFunctions(funcStr): int b = 324; int c = 0; c = a + b; + for (int i = 0; i < 10; i++) { + c = a + b; + } } ''' - returnTypes, funcNames, codes = CPPParser.parseFunctions(sampleCode) - for i in range(len(returnTypes)): - print(returnTypes[i]) - print(funcNames[i]) - print(codes[i]) - # print(returnType, funcName) \ No newline at end of file + # returnTypes, funcNames, codes = CPPParser.parseFunctions(sampleCode) + # for i in range(len(returnTypes)): + # print(returnTypes[i]) + # print(funcNames[i]) + # print(codes[i]) + # print(returnType, funcName) + + sampleVariables = ''' + int a = 12; int b = 23; + float myVar; float myVar2 = 12.2; + ''' + + types, varNames, initialValues = CPPParser.parseVariables(sampleVariables) + for i in range(len(types)): + print(types[i]) + print(varNames[i]) + print(initialValues[i]) + diff --git a/src/tools/visualStates_py/gui/cpprosgenerator.py b/src/tools/visualStates_py/gui/cpprosgenerator.py index 6979d38a0..7ae7f3b3c 100644 --- a/src/tools/visualStates_py/gui/cpprosgenerator.py +++ b/src/tools/visualStates_py/gui/cpprosgenerator.py @@ -22,18 +22,16 @@ from gui.cmakevars import CMAKE_INSTALL_PREFIX from gui.cppparser import CPPParser from xml.dom import minidom -import os, stat, shutil +import os, stat class CppRosGenerator(CppGenerator): def __init__(self, libraries, config, interfaceHeaders, states): CppGenerator.__init__(self, libraries, config, interfaceHeaders, states) def generate(self, projectPath, projectName): - # create src folder in the projects - if os.path.exists(projectPath + '/src'): - shutil.rmtree(projectPath + '/src') - - os.mkdir(projectPath + '/src') + # create source dir if not exists + if not os.path.exists(projectPath + os.sep + 'src'): + os.makedirs(projectPath + os.sep + 'src') stringList = [] self.generateHeaders(stringList, projectName) @@ -55,10 +53,6 @@ def generate(self, projectPath, projectName): self.generateMain(stringList, projectName) sourceCode = ''.join(stringList) - # create source dir if not exists - if not os.path.exists(projectPath + os.sep + 'src'): - os.makedirs(projectPath + os.sep + 'src') - fp = open(projectPath + os.sep + 'src' + os.sep + projectName + '.cpp', 'w') fp.write(sourceCode) fp.close() @@ -84,8 +78,6 @@ def generate(self, projectPath, projectName): with open(projectPath + os.sep + 'package.xml', 'w') as f: f.write(xmlStr) - self.copyRunTime(projectPath) - def generateHeaders(self, headers, projectName): headers.append('#ifndef ' + projectName + '_H\n') @@ -120,7 +112,9 @@ def generateRosNodeClass(self, classStr, config): classStr.append('\tpthread_t thread;\n\n') for topic in config.getTopics(): - varName = topic['name'].replace('/', '-') + varName = topic['name'].replace('/', '_') + if varName[0] == '_': + varName = varName[1:] if topic['opType'] == 'Publish': classStr.append('\tros::Publisher ' + varName + 'Pub;\n') @@ -144,7 +138,9 @@ def generateRosNodeClass(self, classStr, config): classStr.append('\tvoid join();\n\n') for topic in config.getTopics(): - varName = topic['name'].replace('/', '-') + varName = topic['name'].replace('/', '_') + if varName[0] == '_': + varName = varName[1:] if topic['opType'] == 'Subscribe': type = topic['type'] @@ -161,6 +157,17 @@ def generateRosNodeClass(self, classStr, config): else: classStr.append('\tvoid publish' + varName + '(' + type + '& ' + varName + ');\n') classStr.append('\n') + + for state in self.getAllStates(): + # define variables + types, varNames, initialValues = CPPParser.parseVariables(state.getVariables()) + for i in range(len(types)): + classStr.append('\t' + types[i] + ' ' + varNames[i] + ';\n') + classStr.append('\n') + returnTypes, funcNames, codes = CPPParser.parseFunctions(state.getFunctions()) + for i in range(len(returnTypes)): + classStr.append('\t' + returnTypes[i] + ' ' + funcNames[i] + ';\n') + classStr.append('};\n\n') def generateStateClasses(self, classStr): @@ -168,15 +175,10 @@ def generateStateClasses(self, classStr): classStr.append('class State' + str(state.id) + ' : public State {\n') classStr.append('public:\n') classStr.append('\tRosNode* node;\n') - classStr.append(state.getVariables()) classStr.append('\tState' + str(state.id) + '(int id, bool initial, RosNode* node, int cycleDuration, State* parent, RunTimeGui* gui):\n') classStr.append('\t\tState(id, initial, cycleDuration, parent, gui) {this->node = node;}\n') classStr.append('\tvirtual void runCode();\n') - returnTypes, funcNames, codes = CPPParser.parseFunctions(state.getFunctions()) - for i in range(len(returnTypes)): - classStr.append('\t' + returnTypes[i] + ' ' + funcNames[i] + ';\n') - classStr.append('};\n\n') def generateTransitionClasses(self, classStr): @@ -203,14 +205,16 @@ def generateHeadersForCpp(self, headerStr, projectName): headerStr.append('#include \n') headerStr.append('#include \n') headerStr.append('#include \n') - headerStr.append('#include \n') - headerStr.append('#include \n\n'); + headerStr.append('#include \n\n') def generateRosMethods(self, rosStr, config): rosStr.append('RosNode::RosNode(int nodeRate):rate(nodeRate) {\n') for topic in config.getTopics(): - varName = topic['name'].replace('/', '-') + varName = topic['name'].replace('/', '_') + if varName[0] == '_': + varName = varName[1:] + type = topic['type'] types = type.split('/') if topic['opType'] == 'Publish': @@ -221,6 +225,14 @@ def generateRosMethods(self, rosStr, config): 'name'] + '", 10);\n') elif topic['opType'] == 'Subscribe': rosStr.append('\t' + varName + 'Sub = nh.subscribe("' + topic['name'] + '", 10, &RosNode::'+varName+'Callback, this);\n') + + # set inital values of variables + for state in self.getAllStates(): + types, varNames, initialValues = CPPParser.parseVariables(state.getVariables()) + for i in range(len(types)): + if initialValues[i] is not None: + rosStr.append('\t' + varNames[i] + ' = ' + initialValues[i] + ';\n') + rosStr.append('}\n\n') rosStr.append('void* RosNode::threadRunner(void* owner) {\n') @@ -243,7 +255,10 @@ def generateRosMethods(self, rosStr, config): rosStr.append('}\n\n') for topic in config.getTopics(): - varName = topic['name'].replace('/', '-') + varName = topic['name'].replace('/', '_') + if varName[0] == '_': + varName = varName[1:] + if topic['opType'] == 'Subscribe': type = topic['type'] types = type.split('/') @@ -272,6 +287,12 @@ def generateRosMethods(self, rosStr, config): rosStr.append('\t' + varName + 'Pub.publish(' + varName + ');\n') rosStr.append('}\n\n') + for state in self.getAllStates(): + returnTypes, funcNames, codes = CPPParser.parseFunctions(state.getFunctions()) + for i in range(len(returnTypes)): + rosStr.append(returnTypes[i] + ' RosNode::' + funcNames[i] + '\n') + rosStr.append(codes[i]) + rosStr.append('\n\n') def generateReadArgs(self, argStr, projectName): @@ -305,9 +326,7 @@ def generateReadArgs(self, argStr, projectName): ''' argStr.append(mystr) argStr.append('void* runGui(void*) {\n') - argStr.append('\tstd::string path = ros::package::getPath("' + projectName + '");\n') - argStr.append('\tpath.append("/'+projectName+'_runtime.py");\n') - argStr.append('\tsystem(path.c_str());\n') + argStr.append('\tsystem("./' + projectName + '_runtime.py");\n') argStr.append('}\n\n') def parentString(self, state): @@ -361,7 +380,7 @@ def generateMain(self, mainStr, projectName): mainStr.append('\tstate' + str(state.id) + '->startThread();\n') mainStr.append('\n') - mainStr.append('signal(SIGINT, signalCallback);\n') + mainStr.append('\tsignal(SIGINT, signalCallback);\n') for state in self.states: mainStr.append('\tstate' + str(state.id) + '->join();\n') @@ -371,6 +390,7 @@ def generateRunTimeGui(self, guiStr): guiStr.append('#!/usr/bin/python\n') guiStr.append('# -*- coding: utf-8 -*-\n') guiStr.append('import sys\n') + guiStr.append('sys.path.append("' + CMAKE_INSTALL_PREFIX + '/lib/python2.7/visualStates_py")\n\n') guiStr.append('from PyQt5.QtWidgets import QApplication\n') guiStr.append('from codegen.python.runtimegui import RunTimeGui\n\n') @@ -416,22 +436,30 @@ def generateCmake(self, cmakeStr, projectName, config): cmakeStr.append('find_package(catkin REQUIRED COMPONENTS\n') for dep in config.getBuildDependencies(): cmakeStr.append(' ' + dep + '\n') - cmakeStr.append(' roslib\n') cmakeStr.append(')\n\n') cmakeStr.append('SET(JDEROBOT_INSTALL_PATH ' + CMAKE_INSTALL_PREFIX + ')\n') myStr = ''' +SET(JDEROBOT_INCLUDE_DIR ${JDEROBOT_INSTALL_PATH}/include) +SET(VISUALSTATE_RUNTIME_INCLUDE_DIR ${JDEROBOT_INSTALL_PATH}/include/visualstates_py) +SET(JDEROBOT_LIBS_DIR ${JDEROBOT_INSTALL_PATH}/lib) +SET(VISUALSTATE_RUNTIME_LIBS_DIR ${JDEROBOT_INSTALL_PATH}/lib/visualstates_py) + include_directories( ${catkin_INCLUDE_DIRS} - src + ${JDEROBOT_INCLUDE_DIR} + ${VISUALSTATE_RUNTIME_INCLUDE_DIR} ) +link_directories( + ${JDEROBOT_LIBS_DIR} + ${VISUALSTATE_RUNTIME_LIBS_DIR} +) ''' cmakeStr.append(myStr) cmakeStr.append('catkin_package()\n') - cmakeStr.append('add_executable(' + projectName + '\n src/' + projectName + '.cpp\n src/runtimegui.cpp\n \ - src/state.cpp\n src/temporaltransition.cpp\n src/transition.cpp\n )\n') - cmakeStr.append('target_link_libraries(' + projectName + ' ${catkin_LIBRARIES})\n') + cmakeStr.append('add_executable(' + projectName + ' src/' + projectName + '.cpp)\n') + cmakeStr.append('target_link_libraries(' + projectName + ' ${catkin_LIBRARIES} visualStatesRunTime)\n') cmakeStr.append('install(TARGETS ' + projectName + ' RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})\n\n') return cmakeStr @@ -462,19 +490,11 @@ def generatePackageXml(self, config, projectName): bdepElement.appendChild(doc.createTextNode(bdep)) root.appendChild(bdepElement) - bdepElement = doc.createElement('build_depend') - bdepElement.appendChild(doc.createTextNode('roslib')) - root.appendChild(bdepElement) - for rdep in config.getRunDependencies(): rdepElement = doc.createElement('run_depend') rdepElement.appendChild(doc.createTextNode(rdep)) root.appendChild(rdepElement) - rdepElement = doc.createElement('run_depend') - rdepElement.appendChild(doc.createTextNode('roslib')) - root.appendChild(rdepElement) - exportElement = doc.createElement('export') root.appendChild(exportElement) doc.appendChild(root) @@ -482,37 +502,6 @@ def generatePackageXml(self, config, projectName): return doc - def copyRunTime(self, projectPath): - if os.path.exists(projectPath + '/codegen'): - shutil.rmtree(projectPath + '/codegen') - if os.path.exists(projectPath + '/gui'): - shutil.rmtree(projectPath + '/gui') - - shutil.copytree(CMAKE_INSTALL_PREFIX + '/lib/python2.7/visualStates_py/codegen', projectPath + '/codegen') - shutil.copytree(CMAKE_INSTALL_PREFIX + '/lib/python2.7/visualStates_py/gui', projectPath + '/gui') - - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/conditionaltransition.h', - projectPath + '/src/conditionaltransition.h') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/runtimegui.h', - projectPath + '/src/runtimegui.h') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/runtimegui.cpp', - projectPath + '/src/runtimegui.cpp') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/state.h', - projectPath + '/src/state.h') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/state.cpp', - projectPath + '/src/state.cpp') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/temporaltransition.h', - projectPath + '/src/temporaltransition.h') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/temporaltransition.cpp', - projectPath + '/src/temporaltransition.cpp') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/transition.h', - projectPath + '/src/transition.h') - shutil.copy(CMAKE_INSTALL_PREFIX + '/share/visualstates_py/transition.cpp', - projectPath + '/src/transition.cpp') - - - - diff --git a/src/tools/visualStates_py/gui/pythongenerator.py b/src/tools/visualStates_py/gui/pythongenerator.py index 763a10b14..f0025de4c 100644 --- a/src/tools/visualStates_py/gui/pythongenerator.py +++ b/src/tools/visualStates_py/gui/pythongenerator.py @@ -74,9 +74,6 @@ def generate(self, projectPath, projectName): fp.close() self.generateAndSaveCfgYaml(projectPath, projectName) - #fp = open(projectPath + os.sep + projectName + '.cfg', 'w') - #fp.write(''.join(stringList)) - #fp.close() os.system('chmod +x ' + projectPath + os.sep + projectName + '.py') @@ -108,8 +105,6 @@ def generateImports(self, headerStr): # headerStr.append(cfg['interface']) # headerStr.append('Prx\n') - headerStr.append('import comm\n') - headerStr.append('\n') return headerStr @@ -125,13 +120,7 @@ def generateStateClass(self, state, stateStr): stateStr.append('\tdef __init__(self, id, initial, interfaces, cycleDuration, parent=None, gui=None):\n') stateStr.append('\t\tState.__init__(self, id, initial, cycleDuration, parent, gui)\n') - stateStr.append('\t\tself.interfaces = interfaces\n') - - if len(state.getVariables()) > 0: - for varLine in state.getVariables().split('\n'): - stateStr.append('\t\t' + varLine + '\n') - stateStr.append('\n') - stateStr.append('\n') + stateStr.append('\t\tself.interfaces = interfaces\n\n') stateStr.append('\tdef runCode(self):\n') if len(state.getCode()) > 0: @@ -141,10 +130,6 @@ def generateStateClass(self, state, stateStr): stateStr.append('\t\tpass\n') stateStr.append('\n') - if len(state.getFunctions()) > 0: - for funcLine in state.getFunctions().split('\n'): - stateStr.append('\t' + funcLine + '\n') - stateStr.append('\n') def generateInterfaces(self, interfaceStr, projectName): mystr = '''class Interfaces(): @@ -155,6 +140,15 @@ def generateInterfaces(self, interfaceStr, projectName): for cfg in self.config.getInterfaces(): interfaceStr.append('\t\tself.' + cfg['name'] + ' = None\n') + for state in self.getAllStates(): + if len(state.getVariables()) > 0: + for varLine in state.getVariables().split('\n'): + varLine = varLine.strip() + if len(varLine) > 0: + interfaceStr.append('\t\t' + varLine + '\n') + + interfaceStr.append('\n') + interfaceStr.append('\t\tself.connectProxies()\n\n') interfaceStr.append('\tdef connectProxies(self):\n') @@ -173,20 +167,25 @@ def generateInterfaces(self, interfaceStr, projectName): interfaceStr.append('\t\tif self.jdrc is not None:\n') interfaceStr.append('\t\t\tself.jdrc.destroy()\n\n') + for state in self.getAllStates(): + if len(state.getFunctions()) > 0: + for funcLine in state.getFunctions().split('\n'): + interfaceStr.append('\t' + funcLine + '\n') + interfaceStr.append('\n') + def generateTransitionClasses(self, tranStr): for tran in self.getAllTransitions(): if tran.getType() == TransitionType.CONDITIONAL: tranStr.append('class Tran' + str(tran.id) + '(ConditionalTransition):\n') - tranStr.append('\tdef __init__(self, id, destinationId, interfaces)\n') + tranStr.append('\tdef __init__(self, id, destinationId, interfaces):\n') tranStr.append('\t\tConditionalTransition.__init__(self, id, destinationId)\n') tranStr.append('\t\tself.interfaces = interfaces\n\n') tranStr.append('\tdef checkCondition(self):\n') for checkLine in tran.getCondition().split('\n'): - tranStr.append('\t\treturn ' + checkLine + '\n') + tranStr.append('\t\t' + checkLine + '\n') tranStr.append('\n') elif tran.getType() == TransitionType.TEMPORAL: tranStr.append('class Tran' + str(tran.id) + '(TemporalTransition):\n\n') - tranStr.append('\tdef runCode(self):\n') if len(tran.getCode()) > 0: for codeLine in tran.getCode().split('\n'): diff --git a/src/tools/visualStates_py/gui/pythonrosgenerator.py b/src/tools/visualStates_py/gui/pythonrosgenerator.py index 84d88ce1d..d417a124d 100644 --- a/src/tools/visualStates_py/gui/pythonrosgenerator.py +++ b/src/tools/visualStates_py/gui/pythonrosgenerator.py @@ -134,13 +134,7 @@ def generateStateClass(self, state, stateStr): stateStr.append('\tdef __init__(self, id, initial, rosNode, cycleDuration, parent=None, gui=None):\n') stateStr.append('\t\tState.__init__(self, id, initial, cycleDuration, parent, gui)\n') - stateStr.append('\t\tself.rosNode = rosNode\n') - - if len(state.getVariables()) > 0: - for varLine in state.getVariables().split('\n'): - stateStr.append('\t\t' + varLine + '\n') - stateStr.append('\n') - stateStr.append('\n') + stateStr.append('\t\tself.rosNode = rosNode\n\n') stateStr.append('\tdef runCode(self):\n') if len(state.getCode()) > 0: @@ -148,12 +142,7 @@ def generateStateClass(self, state, stateStr): stateStr.append('\t\t' + codeLine + '\n') else: stateStr.append('\t\tpass\n') - stateStr.append('\n') - - if len(state.getFunctions()) > 0: - for funcLine in state.getFunctions().split('\n'): - stateStr.append('\t' + funcLine + '\n') - stateStr.append('\n') + stateStr.append('\n\n') def generateRosInterface(self, rosNodeStr, projectName): rosNodeStr.append('class RosNode():\n') @@ -163,14 +152,22 @@ def generateRosInterface(self, rosNodeStr, projectName): if topic['opType'] == 'Publish': typesStr = topic['type'] types = typesStr.split('/') - rosNodeStr.append('\t\tself.' + topic['name'] + 'Pub = rospy.Publisher("' + + rosNodeStr.append('\t\tself.' + self.getVarName(topic['name']) + 'Pub = rospy.Publisher("' + topic['name'] + '", ' + types[1] + ', queue_size=10)\n') elif topic['opType'] == 'Subscribe': typesStr = topic['type'] types = typesStr.split('/') - rosNodeStr.append('\t\tself.' + topic['name'] + 'Sub = rospy.Subscriber("' + - topic['name'] + '", ' + types[1] + ', self.'+topic['name']+'Callback)\n') - rosNodeStr.append('\t\tself.' + topic['name'] + ' = ' + types[1] + '()\n') + rosNodeStr.append('\t\tself.' + self.getVarName(topic['name']) + 'Sub = rospy.Subscriber("' + + topic['name'] + '", ' + types[1] + ', self.'+self.getVarName(topic['name'])+'Callback)\n') + rosNodeStr.append('\t\tself.' + self.getVarName(topic['name']) + ' = ' + types[1] + '()\n') + + # add state variables as part of ros node + for state in self.getAllStates(): + if len(state.getVariables()) > 0: + for varLine in state.getVariables().split('\n'): + rosNodeStr.append('\t\t' + varLine + '\n') + rosNodeStr.append('\n') + rosNodeStr.append('\t\ttime.sleep(1) # wait for initialization of the node, subscriber, and publisher\n\n') rosNodeStr.append('\tdef stop(self):\n') @@ -179,13 +176,21 @@ def generateRosInterface(self, rosNodeStr, projectName): # define publisher methods and subscriber callbacks for topic in self.config.getTopics(): if topic['opType'] == 'Publish': - rosNodeStr.append('\tdef publish' + topic['name'] + '(self, ' + topic['name'] + '):\n') - rosNodeStr.append('\t\tself.' + topic['name'] + 'Pub.publish(' + topic['name'] + ')\n\n') + rosNodeStr.append('\tdef publish' + self.getVarName(topic['name']) + '(self, ' + self.getVarName(topic['name']) + '):\n') + rosNodeStr.append('\t\tself.' + self.getVarName(topic['name']) + 'Pub.publish(' + self.getVarName(topic['name']) + ')\n\n') elif topic['opType'] == 'Subscribe': - rosNodeStr.append('\tdef ' + topic['name'] + 'Callback(self, ' + topic['name'] + '):\n') - rosNodeStr.append('\t\tself.' + topic['name'] + ' = ' + topic['name'] + '\n') + rosNodeStr.append('\tdef ' + self.getVarName(topic['name']) + 'Callback(self, ' + self.getVarName(topic['name']) + '):\n') + rosNodeStr.append('\t\tself.' + self.getVarName(topic['name']) + ' = ' + self.getVarName(topic['name']) + '\n') rosNodeStr.append('\n\n') + # define user functions as part of rosnode + for state in self.getAllStates(): + if len(state.getFunctions()) > 0: + for funcLine in state.getFunctions().split('\n'): + rosNodeStr.append('\t' + funcLine + '\n') + rosNodeStr.append('\n\n') + + def generateTransitionClasses(self, tranStr): for tran in self.getAllTransitions(): if tran.getType() == TransitionType.CONDITIONAL: @@ -195,7 +200,7 @@ def generateTransitionClasses(self, tranStr): tranStr.append('\t\tself.rosNode = rosNode\n\n') tranStr.append('\tdef checkCondition(self):\n') for checkLine in tran.getCondition().split('\n'): - tranStr.append('\t\treturn ' + checkLine + '\n') + tranStr.append('\t\t' + checkLine + '\n') tranStr.append('\n') elif tran.getType() == TransitionType.TEMPORAL: tranStr.append('class Tran' + str(tran.id) + '(TemporalTransition):\n\n') @@ -366,8 +371,15 @@ def generatePackageXml(self, config, projectName): def copyRuntime(self, projectPath): if os.path.exists(projectPath + '/codegen'): shutil.rmtree(projectPath + '/codegen') - if os.path.exists(projectPath + 'gui'): + if os.path.exists(projectPath + '/gui'): shutil.rmtree(projectPath + '/gui') shutil.copytree(CMAKE_INSTALL_PREFIX + '/lib/python2.7/visualStates_py/codegen', projectPath + '/codegen') - shutil.copytree(CMAKE_INSTALL_PREFIX + '/lib/python2.7/visualStates_py/gui', projectPath + '/gui') \ No newline at end of file + shutil.copytree(CMAKE_INSTALL_PREFIX + '/lib/python2.7/visualStates_py/gui', projectPath + '/gui') + + + def getVarName(self, varName): + varName = varName.replace('/', '_') + if varName[0] == '_': + varName = varName[1:] + return varName \ No newline at end of file diff --git a/src/tools/visualStates_py/gui/state.py b/src/tools/visualStates_py/gui/state.py index 1045b3eee..54382b1f4 100644 --- a/src/tools/visualStates_py/gui/state.py +++ b/src/tools/visualStates_py/gui/state.py @@ -100,8 +100,15 @@ def getNewCopy(self): copy.y = self.y return copy - def parse(self, stateElement): + def parseElement(self, elementName, parentElement): + elements = parentElement.getElementsByTagName(elementName) + if len(elements) > 0: + if len(elements[0].childNodes) > 0: + return elements[0].childNodes[0].nodeValue + return '' + + def parse(self, stateElement): # parse attributes of the state for (name, value) in stateElement.attributes.items(): if name == 'id': @@ -114,15 +121,10 @@ def parse(self, stateElement): self.x = float(stateElement.getElementsByTagName('posx')[0].childNodes[0].nodeValue) self.y = float(stateElement.getElementsByTagName('posy')[0].childNodes[0].nodeValue) - # optinal state tags - if len(stateElement.getElementsByTagName('code')[0].childNodes) > 0: - self.code = stateElement.getElementsByTagName('code')[0].childNodes[0].nodeValue - - if len(stateElement.getElementsByTagName('functions')[0].childNodes) > 0: - self.functions = stateElement.getElementsByTagName('functions')[0].childNodes[0].nodeValue - - if len(stateElement.getElementsByTagName('timestep')[0].childNodes) > 0: - self.timeStepDuration = int(stateElement.getElementsByTagName('timestep')[0].childNodes[0].nodeValue) + self.code = self.parseElement('code', stateElement) + self.functions = self.parseElement('functions', stateElement) + self.variables = self.parseElement('variables', stateElement) + self.timeStepDuration = int((self.parseElement('timestep', stateElement))) # recursive child state parsing allChildTransitions = [] @@ -148,6 +150,7 @@ def parse(self, stateElement): # return transitions of the state to be able to wire after all states are created return stateTransitions + def createElement(self, doc, parentElement=None): stateElement = doc.createElement('state') stateElement.setAttribute('initial', str(self.initial)) @@ -167,6 +170,9 @@ def createElement(self, doc, parentElement=None): functionsElement = doc.createElement('functions') functionsElement.appendChild(doc.createTextNode(self.functions)) stateElement.appendChild(functionsElement) + varElement = doc.createElement('variables') + varElement.appendChild(doc.createTextNode(self.variables)) + stateElement.appendChild(varElement) timeElement = doc.createElement('timestep') timeElement.appendChild(doc.createTextNode(str(self.timeStepDuration))) stateElement.appendChild(timeElement) diff --git a/src/tools/visualStates_py/install_manifest.txt b/src/tools/visualStates_py/install_manifest.txt new file mode 100644 index 000000000..344a62917 --- /dev/null +++ b/src/tools/visualStates_py/install_manifest.txt @@ -0,0 +1,30 @@ +/opt/jderobot/lib/visualstates_py/libvisualStatesRunTime.so +/opt/jderobot/include/visualstates_py//runtimegui.h +/opt/jderobot/include/visualstates_py//test.h +/opt/jderobot/include/visualstates_py//transition.h +/opt/jderobot/include/visualstates_py//conditionaltransition.h +/opt/jderobot/include/visualstates_py//temporaltransition.h +/opt/jderobot/include/visualstates_py//state.h +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//conditionaltransition.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//transition.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//state.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//test.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//temporaltransition.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//__init__.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//testipc.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python//runtimegui.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/state.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/transition.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/guitransition.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/guistate.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/idtextboxgraphicsitem.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/recthandlegraphicsitem.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/transitiontype.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/treemodel.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/treenode.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/cmakevars.py +/opt/jderobot/lib/python2.7/visualStates_py/__init__.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/__init__.py +/opt/jderobot/lib/python2.7/visualStates_py/codegen/python/__init__.py +/opt/jderobot/lib/python2.7/visualStates_py/gui/__init__.py +/opt/jderobot/bin/getinterfaces.sh \ No newline at end of file diff --git a/src/tools/visualStates_py/samples/sample1/CMakeLists.txt b/src/tools/visualStates_py/samples/sample1/CMakeLists.txt new file mode 100644 index 000000000..6a36833d7 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample1/CMakeLists.txt @@ -0,0 +1,46 @@ +project(sample1) + +cmake_minimum_required(VERSION 2.8) + +SET(SOURCE_FILES + sample1.cpp) + +SET(JDEROBOT_INSTALL_PATH /opt/jderobot) + + +SET(JDEROBOT_INCLUDE_DIR ${JDEROBOT_INSTALL_PATH}/include) +SET(VISUALSTATE_RUNTIME_INCLUDE_DIR ${JDEROBOT_INSTALL_PATH}/include/visualstates_py) + +SET(JDEROBOT_LIBS_DIR ${JDEROBOT_INSTALL_PATH}/lib) +SET(VISUALSTATE_RUNTIME_LIBS_DIR ${JDEROBOT_INSTALL_PATH}/lib/visualstates_py) + +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=gnu++0x") + +include_directories( + ${JDEROBOT_INCLUDE_DIR} + ${VISUALSTATE_RUNTIME_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +link_directories( + ${JDEROBOT_LIBS_DIR} + ${VISUALSTATE_RUNTIME_LIBS_DIR} +) + +add_executable(sample1 ${SOURCE_FILES}) + +target_link_libraries( sample1 + visualStatesRunTime + comm + config + JderobotInterfaces + jderobotutil + colorspacesmm + pthread + Ice + IceUtil + IceStorm + glog +) diff --git a/src/tools/visualStates_py/samples/sample1/sample1 b/src/tools/visualStates_py/samples/sample1/sample1 new file mode 100755 index 000000000..d7f716835 Binary files /dev/null and b/src/tools/visualStates_py/samples/sample1/sample1 differ diff --git a/src/tools/visualStates_py/samples/sample1/sample1.cpp b/src/tools/visualStates_py/samples/sample1/sample1.cpp new file mode 100644 index 000000000..a3859f62b --- /dev/null +++ b/src/tools/visualStates_py/samples/sample1/sample1.cpp @@ -0,0 +1,106 @@ +#include "sample1.h" +#include +#include +#include + +void State0::runCode() { + +} + +void State1::runCode() { + interfaces->myMotors->sendV(0.1); +} + +void State2::runCode() { + interfaces->myMotors->sendV(0); +} + +void Tran1::runCode() { + +} + +void Tran2::runCode() { + +} + +void Interfaces::connectProxies(int argc, char* argv[]) { + Config::Properties props = Config::load(argc, argv); + jdrc = new Comm::Communicator(props); + + myMotors = Comm::getMotorsClient(jdrc, "sample1.myMotors"); + if (myMotors == NULL) { + throw "invalid proxy myMotors"; + } + std::cout << "myMotors is connected" << std::endl; +} + +void Interfaces::destroyProxies() { + if (jdrc != 0) { + } +} + + +pthread_t guiThread; +RunTimeGui* runTimeGui = NULL; +bool displayGui = false; + +void readArgs(int *argc, char* argv[]) { + int i; + std::string splitedArg; + + for(i = 0; i < *argc; i++) { + splitedArg = strtok(argv[i], "="); + if (splitedArg.compare("--displaygui") == 0){ + splitedArg = strtok(NULL, "="); + if (splitedArg.compare("true") == 0 || splitedArg.compare("True") == 0){ + displayGui = true; + std::cout << "displayGui ENABLED" << std::endl; + }else{ + displayGui = false; + std::cout << "displayGui DISABLED" << std::endl; + } + } + if(i == *argc -1){ + (*argc)--; + } + } +} + +void* runGui(void*) { + system("./sample1_runtime.py"); +} + +int main(int argc, char* argv[]) { + Interfaces interfaces; + try { + interfaces.connectProxies(argc, argv); + } catch (const Ice::Exception& ex) { + std::cerr << ex << std::endl; + interfaces.destroyProxies(); + return 1; + } catch (const char* msg) { + std::cerr << msg << std::endl; + interfaces.destroyProxies(); + return 1; + } + + readArgs(&argc, argv); + + if (displayGui) { + pthread_create(&guiThread, NULL, &runGui, NULL); + runTimeGui = new RunTimeGui(); + + } + State* state0 = new State0(0, true, &interfaces, 100, NULL, runTimeGui); + State* state1 = new State1(1, true, &interfaces, 100, state0, runTimeGui); + State* state2 = new State2(2, false, &interfaces, 100, state0, runTimeGui); + + Transition* tran1 = new Tran1(1, 2, 1000); + state1->addTransition(tran1); + Transition* tran2 = new Tran2(2, 1, 1000); + state2->addTransition(tran2); + + state0->startThread(); + + state0->join(); +} diff --git a/src/tools/visualStates_py/samples/sample1/sample1.h b/src/tools/visualStates_py/samples/sample1/sample1.h new file mode 100644 index 000000000..ea0ebebce --- /dev/null +++ b/src/tools/visualStates_py/samples/sample1/sample1.h @@ -0,0 +1,58 @@ +#ifndef sample1_H +#define sample1_H + +#include +#include +#include +#include + +#include +#include +#include + +class Interfaces { +public: + Comm::Communicator* jdrc; + Comm::MotorsClient* myMotors; + + virtual void connectProxies(int argc, char* argv[]); + virtual void destroyProxies(); +}; + +class State0 : public State { +public: + Interfaces* interfaces; + State0(int id, bool initial, Interfaces* interfaces, int cycleDuration, State* parent, RunTimeGui* gui): + State(id, initial, cycleDuration, parent, gui) {this->interfaces = interfaces;} + virtual void runCode(); +}; + +class State1 : public State { +public: + Interfaces* interfaces; + State1(int id, bool initial, Interfaces* interfaces, int cycleDuration, State* parent, RunTimeGui* gui): + State(id, initial, cycleDuration, parent, gui) {this->interfaces = interfaces;} + virtual void runCode(); +}; + +class State2 : public State { +public: + Interfaces* interfaces; + State2(int id, bool initial, Interfaces* interfaces, int cycleDuration, State* parent, RunTimeGui* gui): + State(id, initial, cycleDuration, parent, gui) {this->interfaces = interfaces;} + virtual void runCode(); +}; + +class Tran1 : public TemporalTransition { + public: + Tran1(int id, int destId, int elapsedTime):TemporalTransition(id, destId, elapsedTime) {} + virtual void runCode(); +}; + +class Tran2 : public TemporalTransition { + public: + Tran2(int id, int destId, int elapsedTime):TemporalTransition(id, destId, elapsedTime) {} + virtual void runCode(); +}; + +#endif \ No newline at end of file diff --git a/src/tools/visualStates_py/samples/sample1/sample1.py b/src/tools/visualStates_py/samples/sample1/sample1.py new file mode 100755 index 000000000..02fd6b4d1 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample1/sample1.py @@ -0,0 +1,153 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import sys, threading, time, signal +sys.path.append("/opt/jderobot/lib/python2.7") +sys.path.append("/opt/jderobot/lib/python2.7/visualStates_py") +from codegen.python.state import State +from codegen.python.temporaltransition import TemporalTransition +from codegen.python.conditionaltransition import ConditionalTransition +from codegen.python.runtimegui import RunTimeGui +from PyQt5.QtWidgets import QApplication +import config, comm + +import comm + +class State0(State): + def __init__(self, id, initial, interfaces, cycleDuration, parent=None, gui=None): + State.__init__(self, id, initial, cycleDuration, parent, gui) + self.interfaces = interfaces + + def runCode(self): + pass + + +class State1(State): + def __init__(self, id, initial, interfaces, cycleDuration, parent=None, gui=None): + State.__init__(self, id, initial, cycleDuration, parent, gui) + self.interfaces = interfaces + + def runCode(self): + self.interfaces.myMotors.sendV(0.1) + + +class State2(State): + def __init__(self, id, initial, interfaces, cycleDuration, parent=None, gui=None): + State.__init__(self, id, initial, cycleDuration, parent, gui) + self.interfaces = interfaces + + def runCode(self): + pass + + +class Tran1(TemporalTransition): + + def runCode(self): + pass + +class Tran2(TemporalTransition): + + def runCode(self): + pass + +class Interfaces(): + def __init__(self): + self.jdrc = None + self.myMotors = None + self.connectProxies() + + def connectProxies(self): + cfg = config.load(sys.argv[1]) + self.jdrc = comm.init(cfg, "sample1") + self.myMotors = self.jdrc.getMotorsClient("sample1.myMotors") + if not self.myMotors: + raise Exception("could not create client with name:myMotors") + print("myMotors is connected") + + def destroyProxies(self): + if self.jdrc is not None: + self.jdrc.destroy() + +displayGui = False +guiThread = None +gui = None +state0 = None + +def signal_handler(signal, frame): + global gui + print("SIGINT is captured. The program exits") + if gui is not None: + gui.close() + global state0 + state0.stop() + +def readArgs(): + global displayGui + for arg in sys.argv: + splitedArg = arg.split('=') + if splitedArg[0] == '--displaygui': + if splitedArg[1] == 'True' or splitedArg[1] == 'true': + displayGui = True + print('runtime gui enabled') + else: + displayGui = False + print('runtime gui disabled') + +def runGui(): + global gui + app = QApplication(sys.argv) + gui = RunTimeGui() + gui.show() + app.exec_() + +if __name__ == "__main__": + interfaces = Interfaces() + + readArgs() + if displayGui: + guiThread = threading.Thread(target=runGui) + guiThread.start() + + + if displayGui: + while(gui is None): + time.sleep(0.1) + + gui.addState(0, "root", True, 0.0, 0.0, None) + gui.addState(1, "state 1", True, 848.0, 820.0, 0) + gui.addState(2, "state 2", False, 1050.0, 1061.0, 0) + + gui.addTransition(1, "transition 1", 1, 2, 1029.0, 867.5) + gui.addTransition(2, "transition 2", 2, 1, 853.0, 968.5) + + if displayGui: + gui.emitLoadFromRoot() + gui.emitActiveStateById(0) + + state0 = State0(0, True, interfaces, 100, None, gui) + state1 = State1(1, True, interfaces, 100, state0, gui) + state2 = State2(2, False, interfaces, 100, state0, gui) + + tran1 = Tran1(1, 2, 1000) + state1.addTransition(tran1) + + tran2 = Tran2(2, 1, 1000) + state2.addTransition(tran2) + + try: + state0.startThread() + signal.signal(signal.SIGINT, signal_handler) + signal.pause() + state0.join() + if displayGui: + guiThread.join() + + interfaces.destroyProxies() + except: + state0.stop() + if displayGui: + gui.close() + guiThread.join() + + state0.join() + interfaces.destroyProxies() + sys.exit(1) diff --git a/src/tools/visualStates_py/samples/sample1/sample1.xml b/src/tools/visualStates_py/samples/sample1/sample1.xml new file mode 100644 index 000000000..5c7d64072 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample1/sample1.xml @@ -0,0 +1,61 @@ + + + + + + ice + myMotors + + Motors + localhost + 9001 + Motors + + + + + + 0.0 + 0.0 + root + + + 100 + + 848.0 + 820.0 + state 1 + self.interfaces.myMotors.sendV(0.1) + + 100 + + 0 + + 1029.0 + 867.5 + transition 1 + 1 + 2 + + + + + 1050.0 + 1061.0 + state 2 + + + 100 + + 0 + + 853.0 + 968.5 + transition 2 + 2 + 1 + + + + + diff --git a/src/tools/visualStates_py/samples/sample1/sample1.yml b/src/tools/visualStates_py/samples/sample1/sample1.yml new file mode 100644 index 000000000..4d9f36071 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample1/sample1.yml @@ -0,0 +1,7 @@ +sample1: + NodeName: sample1 + myMotors: + Name: myMotors + Proxy: Motors:default -h localhost -p 9001 + Server: 1 + Topic: '' diff --git a/src/tools/visualStates_py/samples/sample1/sample1_runtime.py b/src/tools/visualStates_py/samples/sample1/sample1_runtime.py new file mode 100755 index 000000000..3f207a9da --- /dev/null +++ b/src/tools/visualStates_py/samples/sample1/sample1_runtime.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import sys +sys.path.append("/opt/jderobot/lib/python2.7/visualStates_py") + +from PyQt5.QtWidgets import QApplication +from codegen.python.runtimegui import RunTimeGui + +gui = None + +def runGui(): + global gui + app = QApplication(sys.argv) + gui = RunTimeGui() + gui.activateIPC() + + gui.addState(0, "root", True, 0.0, 0.0, None) + gui.addState(1, "state 1", True, 848.0, 820.0, 0) + gui.addState(2, "state 2", False, 1050.0, 1061.0, 0) + + gui.addTransition(1, "transition 1", 1, 2, 1029.0, 867.5) + gui.addTransition(2, "transition 2", 2, 1, 853.0, 968.5) + + gui.emitLoadFromRoot() + gui.emitActiveStateById(0) + gui.show() + app.exec_() + +if __name__ == "__main__": + runGui() + diff --git a/src/tools/visualStates_py/samples/sample2/CMakeLists.txt b/src/tools/visualStates_py/samples/sample2/CMakeLists.txt new file mode 100644 index 000000000..96faeefe5 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample2/CMakeLists.txt @@ -0,0 +1,44 @@ +project(sample2) + +cmake_minimum_required(VERSION 2.8) + +SET(SOURCE_FILES + sample2.cpp) + +SET(JDEROBOT_INSTALL_PATH /opt/jderobot) + + +SET(JDEROBOT_INCLUDE_DIR ${JDEROBOT_INSTALL_PATH}/include) +SET(VISUALSTATE_RUNTIME_INCLUDE_DIR ${JDEROBOT_INSTALL_PATH}/include/visualstates_py) + +SET(JDEROBOT_LIBS_DIR ${JDEROBOT_INSTALL_PATH}/lib) +SET(VISUALSTATE_RUNTIME_LIBS_DIR ${JDEROBOT_INSTALL_PATH}/lib/visualstates_py) + +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +include_directories( + ${JDEROBOT_INCLUDE_DIR} + ${VISUALSTATE_RUNTIME_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +link_directories( + ${JDEROBOT_LIBS_DIR} + ${VISUALSTATE_RUNTIME_LIBS_DIR} +) + +add_executable(sample2 ${SOURCE_FILES}) + +target_link_libraries( sample2 +visualStatesRunTime + config + comm + JderobotInterfaces + jderobotutil + colorspacesmm + pthread + Ice + IceUtil + IceStorm + glog +) diff --git a/src/tools/visualStates_py/samples/sample2/sample2.cpp b/src/tools/visualStates_py/samples/sample2/sample2.cpp new file mode 100644 index 000000000..bac72f1f8 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample2/sample2.cpp @@ -0,0 +1,106 @@ +#include "sample2.h" +#include +#include +#include + +void State0::runCode() { + +} + +void State1::runCode() { + +} + +void State2::runCode() { + +} + +void Tran1::runCode() { + +} + +void Tran2::runCode() { + +} + +void Interfaces::connectProxies(int argc, char* argv[]) { + Config::Properties props = Config::load(argc, argv); + jdrc = new Comm::Communicator(props); + + pose3d = Comm::getPose3dClient(jdrc, "sample2.pose3d"); + if (pose3d == NULL) { + throw "invalid proxy pose3d"; + } + std::cout << "pose3d is connected" << std::endl; +} + +void Interfaces::destroyProxies() { + if (jdrc != 0) { + } +} + + +pthread_t guiThread; +RunTimeGui* runTimeGui = NULL; +bool displayGui = false; + +void readArgs(int *argc, char* argv[]) { + int i; + std::string splitedArg; + + for(i = 0; i < *argc; i++) { + splitedArg = strtok(argv[i], "="); + if (splitedArg.compare("--displaygui") == 0){ + splitedArg = strtok(NULL, "="); + if (splitedArg.compare("true") == 0 || splitedArg.compare("True") == 0){ + displayGui = true; + std::cout << "displayGui ENABLED" << std::endl; + }else{ + displayGui = false; + std::cout << "displayGui DISABLED" << std::endl; + } + } + if(i == *argc -1){ + (*argc)--; + } + } +} + +void* runGui(void*) { + system("./sample2_runtime.py"); +} + +int main(int argc, char* argv[]) { + Interfaces interfaces; + try { + interfaces.connectProxies(argc, argv); + } catch (const Ice::Exception& ex) { + std::cerr << ex << std::endl; + interfaces.destroyProxies(); + return 1; + } catch (const char* msg) { + std::cerr << msg << std::endl; + interfaces.destroyProxies(); + return 1; + } + + readArgs(&argc, argv); + + if (displayGui) { + pthread_create(&guiThread, NULL, &runGui, NULL); + runTimeGui = new RunTimeGui(); + + } + State* state0 = new State0(0, true, &interfaces, 100, NULL, runTimeGui); + State* state1 = new State1(1, true, &interfaces, 100, state0, runTimeGui); + State* state2 = new State2(2, false, &interfaces, 100, state0, runTimeGui); + + Transition* tran1 = new Tran1(1, 2, 1000); + state1->addTransition(tran1); + Transition* tran2 = new Tran2(2, 1, 1000); + state2->addTransition(tran2); + + state0->startThread(); + + state0->join(); +} diff --git a/src/tools/visualStates_py/samples/sample2/sample2.h b/src/tools/visualStates_py/samples/sample2/sample2.h new file mode 100644 index 000000000..78b2d9135 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample2/sample2.h @@ -0,0 +1,58 @@ +#ifndef sample2_H +#define sample2_H + +#include +#include +#include +#include + +#include +#include +#include + +class Interfaces { +public: + Comm::Communicator* jdrc; + Comm::Pose3dClient* pose3d; + + virtual void connectProxies(int argc, char* argv[]); + virtual void destroyProxies(); +}; + +class State0 : public State { +public: + Interfaces* interfaces; + State0(int id, bool initial, Interfaces* interfaces, int cycleDuration, State* parent, RunTimeGui* gui): + State(id, initial, cycleDuration, parent, gui) {this->interfaces = interfaces;} + virtual void runCode(); +}; + +class State1 : public State { +public: + Interfaces* interfaces; + State1(int id, bool initial, Interfaces* interfaces, int cycleDuration, State* parent, RunTimeGui* gui): + State(id, initial, cycleDuration, parent, gui) {this->interfaces = interfaces;} + virtual void runCode(); +}; + +class State2 : public State { +public: + Interfaces* interfaces; + State2(int id, bool initial, Interfaces* interfaces, int cycleDuration, State* parent, RunTimeGui* gui): + State(id, initial, cycleDuration, parent, gui) {this->interfaces = interfaces;} + virtual void runCode(); +}; + +class Tran1 : public TemporalTransition { + public: + Tran1(int id, int destId, int elapsedTime):TemporalTransition(id, destId, elapsedTime) {} + virtual void runCode(); +}; + +class Tran2 : public TemporalTransition { + public: + Tran2(int id, int destId, int elapsedTime):TemporalTransition(id, destId, elapsedTime) {} + virtual void runCode(); +}; + +#endif \ No newline at end of file diff --git a/src/tools/visualStates_py/samples/sample2/sample2.xml b/src/tools/visualStates_py/samples/sample2/sample2.xml new file mode 100644 index 000000000..9fe1678e3 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample2/sample2.xml @@ -0,0 +1,61 @@ + + + + + + ice + pose3d + + pose3d + localhost + 9001 + Pose3d + + + + + + 0.0 + 0.0 + root + + + 100 + + 903.0 + 922.0 + state 1 + + + 100 + + 0 + + 1025.0 + 954.0 + transition 1 + 1 + 2 + + + + + 1031.0 + 1096.0 + state 2 + + + 100 + + 0 + + 860.0 + 1054.0 + transition 2 + 2 + 1 + + + + + diff --git a/src/tools/visualStates_py/samples/sample2/sample2.yml b/src/tools/visualStates_py/samples/sample2/sample2.yml new file mode 100644 index 000000000..f608faf10 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample2/sample2.yml @@ -0,0 +1,7 @@ +sample2: + NodeName: sample2 + pose3d: + Name: pose3d + Proxy: pose3d:default -h localhost -p 9001 + Server: 1 + Topic: '' diff --git a/src/tools/visualStates_py/samples/sample2/sample2_runtime.py b/src/tools/visualStates_py/samples/sample2/sample2_runtime.py new file mode 100755 index 000000000..7d0b34241 --- /dev/null +++ b/src/tools/visualStates_py/samples/sample2/sample2_runtime.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import sys +sys.path.append("/opt/jderobot/lib/python2.7/visualStates_py") + +from PyQt5.QtWidgets import QApplication +from codegen.python.runtimegui import RunTimeGui + +gui = None + +def runGui(): + global gui + app = QApplication(sys.argv) + gui = RunTimeGui() + gui.activateIPC() + + gui.addState(0, "root", True, 0.0, 0.0, None) + gui.addState(1, "state 1", True, 903.0, 922.0, 0) + gui.addState(2, "state 2", False, 1031.0, 1096.0, 0) + + gui.addTransition(1, "transition 1", 1, 2, 1025.0, 954.0) + gui.addTransition(2, "transition 2", 2, 1, 860.0, 1054.0) + + gui.emitLoadFromRoot() + gui.emitActiveStateById(0) + gui.show() + app.exec_() + +if __name__ == "__main__": + runGui() + diff --git a/src/tools/visualStates_py/visualStates_py b/src/tools/visualStates_py/visualStates_py new file mode 100644 index 000000000..1b0b65a8e --- /dev/null +++ b/src/tools/visualStates_py/visualStates_py @@ -0,0 +1,3 @@ +#!/bin/bash + +python /opt/jderobot/lib/python2.7/visualStates_py/visualStates.py $*