00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "AsebaMarxbot.h"
00025 #include "../../common/consts.h"
00026 #include "../../vm/natives.h"
00027 #include "../../transport/buffer/vm-buffer.h"
00028 #include <set>
00029 #include <map>
00030 #include <cassert>
00031 #include <cstring>
00032 #include <algorithm>
00033 #include <iostream>
00034 #include <QString>
00035 #include <QApplication>
00036 #include <QMessageBox>
00037 #include <QDebug>
00038
00043
00044
00045
00046 typedef std::map<AsebaVMState*, Enki::AsebaMarxbot*> VmSocketMap;
00047 static VmSocketMap asebaSocketMaps;
00048
00049 static AsebaNativeFunctionPointer nativeFunctions[] =
00050 {
00051 ASEBA_NATIVES_STD_FUNCTIONS,
00052 };
00053
00054 static const AsebaNativeFunctionDescription* nativeFunctionsDescriptions[] =
00055 {
00056 ASEBA_NATIVES_STD_DESCRIPTIONS,
00057 0
00058 };
00059
00060 extern "C" void AsebaPutVmToSleep(AsebaVMState *vm)
00061 {
00062 }
00063
00064 extern "C" void AsebaSendBuffer(AsebaVMState *vm, const uint8* data, uint16 length)
00065 {
00066 Enki::AsebaMarxbot& marxBot = *asebaSocketMaps[vm];
00067 Dashel::Stream* stream = marxBot.stream;
00068 assert(stream);
00069
00070
00071 uint16 len = length - 2;
00072 stream->write(&len, 2);
00073 stream->write(&vm->nodeId, 2);
00074 stream->write(data, length);
00075 stream->flush();
00076
00077
00078 for (size_t i = 0; i < marxBot.modules.size(); ++i)
00079 {
00080 Enki::AsebaMarxbot::Module& module = *(marxBot.modules[i]);
00081 if (&(module.vm) != vm)
00082 {
00083 module.events.push_back(Enki::AsebaMarxbot::Event(vm->nodeId, data, length));
00084 AsebaProcessIncomingEvents(&(module.vm));
00085 }
00086 }
00087 }
00088
00089 extern "C" uint16 AsebaGetBuffer(AsebaVMState *vm, uint8* data, uint16 maxLength, uint16* source)
00090 {
00091
00092 Enki::AsebaMarxbot& marxBot = *asebaSocketMaps[vm];
00093 for (size_t i = 0; i < marxBot.modules.size(); ++i)
00094 {
00095 Enki::AsebaMarxbot::Module& module = *(marxBot.modules[i]);
00096 if (&(module.vm) == vm)
00097 {
00098 if (module.events.empty())
00099 return 0;
00100
00101
00102 Enki::AsebaMarxbot::Event& event = module.events.front();
00103 *source = event.source;
00104 size_t length = event.data.size();
00105 length = std::min<size_t>(length, maxLength);
00106 memcpy(data, &(event.data[0]), length);
00107 module.events.pop_front();
00108 return length;
00109 }
00110 }
00111 return 0;
00112 }
00113
00114 extern "C" AsebaVMDescription vmLeftMotorDescription;
00115 extern "C" AsebaVMDescription vmRightMotorDescription;
00116 extern "C" AsebaVMDescription vmProximitySensorsDescription;
00117 extern "C" AsebaVMDescription vmDistanceSensorsDescription;
00118
00119 extern "C" const AsebaVMDescription* AsebaGetVMDescription(AsebaVMState *vm)
00120 {
00121 switch (vm->nodeId)
00122 {
00123 case 1: return &vmLeftMotorDescription;
00124 case 2: return &vmRightMotorDescription;
00125 case 3: return &vmProximitySensorsDescription;
00126 case 4: return &vmDistanceSensorsDescription;
00127 default: break;
00128 }
00129 assert(false);
00130 return 0;
00131 }
00132
00133 extern "C" const AsebaNativeFunctionDescription * const * AsebaGetNativeFunctionsDescriptions(AsebaVMState *vm)
00134 {
00135 return nativeFunctionsDescriptions;
00136 }
00137
00138 static const AsebaLocalEventDescription localEvents[] = { { "timer", "periodic timer at 50 Hz" }, { NULL, NULL } };
00139
00140 extern "C" const AsebaLocalEventDescription * AsebaGetLocalEventsDescriptions(AsebaVMState *vm)
00141 {
00142 return localEvents;
00143 }
00144
00145 extern "C" void AsebaNativeFunction(AsebaVMState *vm, uint16 id)
00146 {
00147 nativeFunctions[id](vm);
00148 }
00149
00150 extern "C" void AsebaWriteBytecode(AsebaVMState *vm)
00151 {
00152 }
00153
00154 extern "C" void AsebaResetIntoBootloader(AsebaVMState *vm)
00155 {
00156 }
00157
00158 extern "C" void AsebaAssert(AsebaVMState *vm, AsebaAssertReason reason)
00159 {
00160 std::cerr << "\nFatal error: ";
00161 switch (vm->nodeId)
00162 {
00163 case 1: std::cerr << "left motor module"; break;
00164 case 2: std::cerr << "right motor module"; break;
00165 case 3: std::cerr << "proximity sensors module"; break;
00166 case 4: std::cerr << "distance sensors module"; break;
00167 default: std::cerr << "unknown module"; break;
00168 }
00169 std::cerr << " has produced exception: ";
00170 switch (reason)
00171 {
00172 case ASEBA_ASSERT_UNKNOWN: std::cerr << "undefined"; break;
00173 case ASEBA_ASSERT_UNKNOWN_UNARY_OPERATOR: std::cerr << "unknown unary operator"; break;
00174 case ASEBA_ASSERT_UNKNOWN_BINARY_OPERATOR: std::cerr << "unknown binary operator"; break;
00175 case ASEBA_ASSERT_UNKNOWN_BYTECODE: std::cerr << "unknown bytecode"; break;
00176 case ASEBA_ASSERT_STACK_OVERFLOW: std::cerr << "stack overflow"; break;
00177 case ASEBA_ASSERT_STACK_UNDERFLOW: std::cerr << "stack underflow"; break;
00178 case ASEBA_ASSERT_OUT_OF_VARIABLES_BOUNDS: std::cerr << "out of variables bounds"; break;
00179 case ASEBA_ASSERT_OUT_OF_BYTECODE_BOUNDS: std::cerr << "out of bytecode bounds"; break;
00180 case ASEBA_ASSERT_STEP_OUT_OF_RUN: std::cerr << "step out of run"; break;
00181 case ASEBA_ASSERT_BREAKPOINT_OUT_OF_BYTECODE_BOUNDS: std::cerr << "breakpoint out of bytecode bounds"; break;
00182 case ASEBA_ASSERT_EMIT_BUFFER_TOO_LONG: std::cerr << "tried to emit a buffer too long"; break;
00183 default: std::cerr << "unknown exception"; break;
00184 }
00185 std::cerr << ".\npc = " << vm->pc << ", sp = " << vm->sp;
00186 std::cerr << "\nResetting VM" << std::endl;
00187 assert(false);
00188 AsebaVMInit(vm);
00189 }
00190
00191 namespace Enki
00192 {
00193 using namespace Dashel;
00194
00195 int AsebaMarxbot::marxbotNumber = 0;
00196
00197 AsebaMarxbot::Module::Module()
00198 {
00199 bytecode.resize(512);
00200 vm.bytecode = &bytecode[0];
00201 vm.bytecodeSize = bytecode.size();
00202
00203 stack.resize(64);
00204 vm.stack = &stack[0];
00205 vm.stackSize = stack.size();
00206 }
00207
00208 AsebaMarxbot::AsebaMarxbot() :
00209 stream(0)
00210 {
00211
00212 leftMotor.vm.nodeId = 1;
00213 leftMotorVariables.id = 1;
00214 leftMotor.vm.variables = reinterpret_cast<sint16 *>(&leftMotorVariables);
00215 leftMotor.vm.variablesSize = sizeof(leftMotorVariables) / sizeof(sint16);
00216 modules.push_back(&leftMotor);
00217
00218 rightMotor.vm.nodeId = 2;
00219 rightMotorVariables.id = 2;
00220 rightMotor.vm.variables = reinterpret_cast<sint16 *>(&rightMotorVariables);
00221 rightMotor.vm.variablesSize = sizeof(rightMotorVariables) / sizeof(sint16);
00222 modules.push_back(&rightMotor);
00223
00224 proximitySensors.vm.nodeId = 3;
00225 proximitySensorVariables.id = 3;
00226 proximitySensors.vm.variables = reinterpret_cast<sint16 *>(&proximitySensorVariables);
00227 proximitySensors.vm.variablesSize = sizeof(proximitySensorVariables) / sizeof(sint16);
00228 modules.push_back(&proximitySensors);
00229
00230 distanceSensors.vm.nodeId = 4;
00231 distanceSensorVariables.id = 4;
00232 distanceSensors.vm.variables = reinterpret_cast<sint16 *>(&distanceSensorVariables);
00233 distanceSensors.vm.variablesSize = sizeof(distanceSensorVariables) / sizeof(sint16);
00234 modules.push_back(&distanceSensors);
00235
00236
00237 asebaSocketMaps[&leftMotor.vm] = this;
00238 asebaSocketMaps[&rightMotor.vm] = this;
00239 asebaSocketMaps[&proximitySensors.vm] = this;
00240 asebaSocketMaps[&distanceSensors.vm] = this;
00241
00242
00243 int port = ASEBA_DEFAULT_PORT + marxbotNumber;
00244 try
00245 {
00246 Dashel::Hub::connect(QString("tcpin:port=%1").arg(port).toStdString());
00247 }
00248 catch (Dashel::DashelException e)
00249 {
00250 QMessageBox::critical(0, QApplication::tr("Aseba Marxbot"), QApplication::tr("Cannot create listening port %0: %1").arg(port).arg(e.what()));
00251 abort();
00252 }
00253 marxbotNumber++;
00254
00255
00256 AsebaVMInit(&leftMotor.vm);
00257 AsebaVMInit(&rightMotor.vm);
00258 AsebaVMInit(&proximitySensors.vm);
00259 AsebaVMInit(&distanceSensors.vm);
00260 }
00261
00262 AsebaMarxbot::~AsebaMarxbot()
00263 {
00264
00265 asebaSocketMaps.erase(&leftMotor.vm);
00266 asebaSocketMaps.erase(&rightMotor.vm);
00267 asebaSocketMaps.erase(&proximitySensors.vm);
00268 asebaSocketMaps.erase(&distanceSensors.vm);
00269 }
00270
00271 void AsebaMarxbot::controlStep(double dt)
00272 {
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 leftSpeed = static_cast<double>(leftMotorVariables.speed) / 100;
00289 rightSpeed = static_cast<double>(rightMotorVariables.speed) / 100;
00290
00291
00292 DifferentialWheeled::controlStep(dt);
00293
00294
00295 int odoLeft = static_cast<int>((leftOdometry * 16 * 134) / (2 * M_PI));
00296 leftMotorVariables.odo[0] = odoLeft & 0xffff;
00297 leftMotorVariables.odo[1] = odoLeft >> 16;
00298
00299 int odoRight = static_cast<int>((rightOdometry * 16 * 134) / (2 * M_PI));
00300 rightMotorVariables.odo[0] = odoRight & 0xffff;
00301 rightMotorVariables.odo[1] = odoRight >> 16;
00302
00303 for (size_t i = 0; i < 24; i++)
00304 proximitySensorVariables.bumpers[i] = static_cast<sint16>(getVirtualBumper(i));
00305 std::fill(proximitySensorVariables.ground, proximitySensorVariables.ground + 12, 0);
00306
00307 for (size_t i = 0; i < 180; i++)
00308 {
00309 if (rotatingDistanceSensor.zbuffer[i] > 32767)
00310 distanceSensorVariables.distances[i] = 32767;
00311 else
00312 distanceSensorVariables.distances[i] = static_cast<sint16>(rotatingDistanceSensor.zbuffer[i]);
00313 }
00314
00315
00316 Hub::step();
00317
00318 for (size_t i = 0; i < modules.size(); i++)
00319 {
00320 AsebaVMState* vm = &(modules[i]->vm);
00321
00322
00323
00324
00325
00326
00327
00328
00329 AsebaVMRun(vm, 65535);
00330
00331
00332 if (AsebaMaskIsClear(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK) || AsebaMaskIsClear(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00333 AsebaVMSetupEvent(vm, ASEBA_EVENT_LOCAL_EVENTS_START);
00334 }
00335 }
00336
00337 void AsebaMarxbot::connectionCreated(Dashel::Stream *stream)
00338 {
00339 std::string targetName = stream->getTargetName();
00340 if (targetName.substr(0, targetName.find_first_of(':')) == "tcp")
00341 {
00342 qDebug() << this << " : New client connected.";
00343 if (this->stream)
00344 {
00345 closeStream(this->stream);
00346 qDebug() << this << " : Disconnected old client.";
00347 }
00348 this->stream = stream;
00349 }
00350 }
00351
00352 void AsebaMarxbot::incomingData(Stream *stream)
00353 {
00354 Event event(stream);
00355
00356
00357 for (size_t i = 0; i < modules.size(); ++i)
00358 {
00359 Module& module = *(modules[i]);
00360 module.events.push_back(event);
00361 AsebaProcessIncomingEvents(&(module.vm));
00362 }
00363 }
00364
00365 void AsebaMarxbot::connectionClosed(Dashel::Stream *stream, bool abnormal)
00366 {
00367 if (stream == this->stream)
00368 {
00369 this->stream = 0;
00370
00371 for (size_t i = 0; i < modules.size(); i++)
00372 (modules[i]->vm).breakpointsCount = 0;
00373 }
00374 if (abnormal)
00375 qDebug() << this << " : Client has disconnected unexpectedly.";
00376 else
00377 qDebug() << this << " : Client has disconnected properly.";
00378 }
00379 }
00380