maked car moks on rapsberry. added handler for route from main server
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Created by user on 7/21/16.
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const main = require("./main.js");
|
||||
const directionClass = main.protoConstructorControl.DirectionRequest;
|
||||
|
||||
function Car(uid) {
|
||||
this.uid = uid;
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.angle = 0;
|
||||
this.velocityMove = 0.1;
|
||||
this.velocityRotation = 10;
|
||||
this.paused = false;
|
||||
this.transportError = false;
|
||||
this.currentDirection = 0;
|
||||
this.executeTimeLeft = 0;
|
||||
this.moveList = [];//object of direction and time to execute this direction. field: direction:byte, executeTime:double (seconds)
|
||||
this.nextMoveListIndex = 0;
|
||||
|
||||
this.reset = reset;
|
||||
this.pause = pause;
|
||||
this.move = move;
|
||||
this.setDirection = setDirection;
|
||||
this.resume = resume;
|
||||
this.getDirectionByte = getDirectionByte;
|
||||
this.setPath = setPath;
|
||||
|
||||
return this;
|
||||
}
|
||||
function reset() {
|
||||
this.currentDirection = 0;
|
||||
this.executeTimeLeft = 0;
|
||||
this.moveList = [];
|
||||
this.nextMoveListIndex = 0;
|
||||
}
|
||||
|
||||
function pause() {
|
||||
this.paused = true;
|
||||
}
|
||||
|
||||
function resume() {
|
||||
this.paused = false;
|
||||
}
|
||||
|
||||
function move(delta) {
|
||||
var deltaSeconds = delta / 1000;
|
||||
// console.log("x=" + this.x + " y=" + this.y + " angle=" + this.angle);
|
||||
if (this.paused) {
|
||||
return;
|
||||
}
|
||||
if (this.executeTimeLeft > 0) {
|
||||
this.executeTimeLeft -= deltaSeconds;
|
||||
if (this.currentDirection == this.getDirectionByte(directionClass.Command.left)) {
|
||||
this.angle += deltaSeconds * this.velocityRotation;
|
||||
} else if (this.currentDirection == this.getDirectionByte(directionClass.Command.right)) {
|
||||
this.angle -= deltaSeconds * this.velocityRotation;
|
||||
} else if (this.currentDirection == this.getDirectionByte(directionClass.Command.forward)) {
|
||||
this.x += this.velocityMove * deltaSeconds * Math.cos(this.angle * Math.PI / 180);
|
||||
this.y += this.velocityMove * deltaSeconds * Math.sin(this.angle * Math.PI / 180);
|
||||
}
|
||||
} else {
|
||||
if (this.nextMoveListIndex == this.moveList.length) {
|
||||
//this was last move point
|
||||
this.setDirection(this.getDirectionByte(directionClass.Command.stop), null)
|
||||
} else {
|
||||
var currentMove = this.moveList[this.nextMoveListIndex];
|
||||
this.currentDirection = currentMove.direction;
|
||||
this.executeTimeLeft = currentMove.executeTime;
|
||||
this.setDirection(this.currentDirection, null);
|
||||
this.nextMoveListIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//args wayPointsList contains object of points. field {distance, angle_delta}. this fun parse this to move list with field direction and move time with using velocity of move and rotation
|
||||
function setPath(wayPointsList) {
|
||||
this.reset();
|
||||
for (var i = 0; i < wayPointsList.length; i++) {
|
||||
var currentPoint = wayPointsList[i];
|
||||
var angle = currentPoint.angle_delta;
|
||||
var distance = currentPoint.distance;
|
||||
if (angle != 0) {
|
||||
//need rotation. check direction left or right
|
||||
if (angle >= 180) {
|
||||
this.moveList.push({
|
||||
"direction": getDirectionByte(directionClass.Command.right),
|
||||
"executeTime": (angle / this.velocityRotation)
|
||||
});
|
||||
} else {
|
||||
this.moveList.push({
|
||||
"direction": getDirectionByte(directionClass.Command.left),
|
||||
"executeTime": (angle / this.velocityRotation)
|
||||
});
|
||||
}
|
||||
}
|
||||
this.moveList.push({
|
||||
"direction": getDirectionByte(directionClass.Command.forward),
|
||||
"executeTime": (distance / this.velocityMove)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setDirection(directionByte, callBack) {
|
||||
fs.appendFile(main.transportFilePath, directionByte, "binary", function (error) {
|
||||
var code = 0;
|
||||
var errorMsg = "";
|
||||
console.log(error);
|
||||
if (error) {
|
||||
errorMsg = error;
|
||||
}
|
||||
if (callBack != null) {
|
||||
callBack(code, errorMsg)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getDirectionByte(command) {
|
||||
resultByte = -1;
|
||||
switch (command) {
|
||||
case directionClass.Command.stop:
|
||||
{
|
||||
resultByte = "0";
|
||||
break;
|
||||
}
|
||||
case directionClass.Command.forward:
|
||||
{
|
||||
resultByte = "1";
|
||||
break;
|
||||
}
|
||||
case directionClass.Command.backward:
|
||||
{
|
||||
resultByte = "2";
|
||||
break;
|
||||
}
|
||||
case directionClass.Command.right:
|
||||
{
|
||||
resultByte = "3";
|
||||
break;
|
||||
}
|
||||
case directionClass.Command.left:
|
||||
{
|
||||
resultByte = "4";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resultByte
|
||||
}
|
||||
|
||||
exports.getCar = Car;
|
||||
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* Created by user on 7/11/16.
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const main = require("./main.js");
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
function loadBin(httpContent, response) {
|
||||
var uploadClass = main.protoConstructorCarkot.Upload;
|
||||
var uploadObject = uploadClass.decode(httpContent);
|
||||
fs.writeFile(main.binFilePath, uploadObject.data.buffer, "binary", function (error) {
|
||||
var uploadResultClass = main.protoConstructorCarkot.UploadResult;
|
||||
var code = 0;
|
||||
var stdErr = "";
|
||||
if (error) {
|
||||
code = 2;
|
||||
stdErr = error.toString();
|
||||
} else {
|
||||
code = 0;
|
||||
var shCommand = main.commandPrefix + " " + main.binFilePath + " " + uploadObject.base;
|
||||
exec(shCommand, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
code = 1;
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
var resultObject = new uploadResultClass({
|
||||
"stdOut": stdout.toString(),
|
||||
"resultCode": code,
|
||||
"stdErr": (stderr.toString() + "\n error:" + error)
|
||||
});
|
||||
var byteBuffer = resultObject.encode();
|
||||
var byteArray = [];
|
||||
for (var i = 0; i < byteBuffer.limit; i++) {
|
||||
byteArray.push(byteBuffer.buffer[i]);
|
||||
}
|
||||
response.writeHead(200, {"Content-Type": "text/plain", "Content-length": byteArray.length});
|
||||
response.write(new Buffer(byteArray));
|
||||
response.end();
|
||||
console.log(shCommand);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function other(httpContent, response) {
|
||||
console.log("other");
|
||||
response.writeHead(200, {"Content-Type": "text/plain"});
|
||||
response.end();
|
||||
}
|
||||
|
||||
//контроль машинкой, как с пульта управления
|
||||
function control(httpContent, response) {
|
||||
var directionClass = main.protoConstructorControl.Direction;
|
||||
var directionObject = directionClass.decode(httpContent);
|
||||
var resultByte;
|
||||
switch (directionObject.command) {
|
||||
case directionClass.Command.stop :
|
||||
{
|
||||
resultByte = "0";
|
||||
break;
|
||||
}
|
||||
case directionClass.Command.forward :
|
||||
{
|
||||
resultByte = "1";
|
||||
break;
|
||||
}
|
||||
|
||||
case directionClass.Command.backward :
|
||||
{
|
||||
resultByte = "2";
|
||||
break;
|
||||
}
|
||||
case directionClass.Command.right :
|
||||
{
|
||||
resultByte = "3";
|
||||
break;
|
||||
}
|
||||
case directionClass.Command.left :
|
||||
{
|
||||
resultByte = "4";
|
||||
break;
|
||||
}
|
||||
}
|
||||
console.log("byte for car: " + resultByte);
|
||||
fs.appendFile(main.transportFilePath, resultByte, "binary", function (error) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
//todo ещё нужно считывать ответ от контроллера и анализировать его (0 или 1) и отправлять
|
||||
response.writeHead(200, {"Content-Type": "text/plain"});
|
||||
response.write(new Buffer([0]));
|
||||
response.end();
|
||||
});
|
||||
}
|
||||
|
||||
exports.loadBin = loadBin;
|
||||
exports.other = other;
|
||||
exports.control = control;
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Created by user on 7/21/16.
|
||||
*/
|
||||
|
||||
const main = require("./../main.js");
|
||||
|
||||
function handle(httpContent, response) {
|
||||
var directionClass = main.protoConstructorControl.DirectionRequest;
|
||||
var directionObject = directionClass.decode(httpContent);
|
||||
var resultByte = main.thisCar.getDirectionByte(directionObject.command);
|
||||
main.thisCar.reset();
|
||||
main.thisCar.moveList.push({
|
||||
"direction": resultByte,
|
||||
"executeTime": 100000
|
||||
});
|
||||
console.log(resultByte);
|
||||
var directionResponse = new main.protoConstructorControl.DirectionResponse({
|
||||
"code": 0,
|
||||
errorMsg: ""
|
||||
});
|
||||
var byteBuffer = directionResponse.encode();
|
||||
var byteArray = [];
|
||||
for (var i = 0; i < byteBuffer.limit; i++) {
|
||||
byteArray.push(byteBuffer.buffer[i]);
|
||||
}
|
||||
response.writeHead(200, {"Content-Type": "text/plain"});
|
||||
response.write(new Buffer(byteArray));
|
||||
response.end();
|
||||
// main.thisCar.setDirection(resultByte, function (code, errorMsg) {
|
||||
// var directionResponse = new main.protoConstructorControl.DirectionResponse({
|
||||
// "code": code,
|
||||
// errorMsg: errorMsg
|
||||
// });
|
||||
// response.writeHead(200, {"Content-Type": "text/plain"});
|
||||
// response.write(directionResponse.encode().buffer);
|
||||
// response.end();
|
||||
// });
|
||||
}
|
||||
|
||||
exports.handler = handle;
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Created by user on 7/21/16.
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const main = require("./../main.js");
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
function handle(httpContent, response) {
|
||||
var uploadClass = main.protoConstructorCarkot.Upload;
|
||||
var uploadObject = uploadClass.decode(httpContent);
|
||||
fs.writeFile(main.binFilePath, uploadObject.data.buffer, "binary", function (error) {
|
||||
var uploadResultClass = main.protoConstructorCarkot.UploadResult;
|
||||
var code = 0;
|
||||
var stdErr = "";
|
||||
if (error) {
|
||||
code = 2;
|
||||
stdErr = error.toString();
|
||||
} else {
|
||||
code = 0;
|
||||
var shCommand = main.commandPrefix + " " + main.binFilePath + " " + uploadObject.base;
|
||||
exec(shCommand, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
code = 1;
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
var resultObject = new uploadResultClass({
|
||||
"stdOut": stdout.toString(),
|
||||
"resultCode": code,
|
||||
"stdErr": (stderr.toString() + "\n error:" + error)
|
||||
});
|
||||
var byteBuffer = resultObject.encode();
|
||||
var byteArray = [];
|
||||
for (var i = 0; i < byteBuffer.limit; i++) {
|
||||
byteArray.push(byteBuffer.buffer[i]);
|
||||
}
|
||||
response.writeHead(200, {"Content-Type": "text/plain", "Content-length": byteArray.length});
|
||||
response.write(new Buffer(byteArray));
|
||||
response.end();
|
||||
console.log(shCommand);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
exports.handler = handle;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Created by user on 7/21/16.
|
||||
*/
|
||||
|
||||
const main = require("./../main.js");
|
||||
|
||||
function handle(httpContent, response) {
|
||||
var routeClass = main.protoConstructorRoute.RouteRequest;
|
||||
var routeObject = routeClass.decode(httpContent);
|
||||
console.log(routeObject)//todo сделать
|
||||
}
|
||||
|
||||
exports.handler = handle;
|
||||
+33
-17
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Created by user on 7/11/16.
|
||||
* Created by maxim zaitsev on 7/11/16.
|
||||
*/
|
||||
|
||||
const server = require("./server.js");
|
||||
@@ -9,11 +9,12 @@ const protoBuf = require("protobufjs");
|
||||
const fs = require("fs");
|
||||
const udev = require("udev");
|
||||
|
||||
//parsing command line args
|
||||
commander
|
||||
.version('1.0.0')
|
||||
.option('-p, --proto [path]', 'path to dir with proto files. need here carkot.proto and route.proto. default ./proto/')
|
||||
.option('-f, --flash [path]', 'path to save bin file with name f.bin. default ./')
|
||||
.option('-s, --serial [path]', 'path to file that represents MCU serial port default ./serial')
|
||||
.option('-f, --flash [path]', 'path to save bin file with name flash.bin. default ./')
|
||||
// .option('-s, --serial [path]', 'path to file that represents MCU serial port default ./serial')//dont need more. use path from udev monitor
|
||||
.parse(process.argv);
|
||||
|
||||
//add slash to end of paths if need
|
||||
@@ -28,30 +29,38 @@ if (commander.flash) {
|
||||
}
|
||||
}
|
||||
|
||||
const builderCarkot = protoBuf.loadProtoFile(commander.protopath ? commander.protopath + "carkot.proto" : "./proto/carkot.proto");
|
||||
const builderControl = protoBuf.loadProtoFile(commander.protopath ? commander.protopath + "route.proto" : "./proto/route.proto");
|
||||
//classes for protobuf decode/encode
|
||||
const builderCarkot = protoBuf.loadProtoFile((commander.protopath ? commander.protopath : "./proto/") + "carkot.proto");
|
||||
const builderControl = protoBuf.loadProtoFile((commander.protopath ? commander.protopath : "./proto/" + "direction.proto"));
|
||||
const builderRoute = protoBuf.loadProtoFile((commander.protopath ? commander.protopath : "./proto/" + "route.proto"));
|
||||
|
||||
var executeShell = "./st-flash";
|
||||
exports.protoConstructorCarkot = builderCarkot.build("carkot");
|
||||
exports.protoConstructorControl = builderControl.build("carkot");
|
||||
exports.protoConstructorRoute = builderRoute.build("carkot");
|
||||
exports.commandPrefix = executeShell + " write";
|
||||
exports.binFilePath = (commander.flash ? commander.flash : "./") + "st-flash";
|
||||
exports.transportFilePath = (commander.serial ? commander.serial : "./serial");
|
||||
exports.binFilePath = (commander.flash ? commander.flash : "./") + "flash.bin";
|
||||
exports.transportFilePath = "";
|
||||
|
||||
var handlers = require("./handlers.js");
|
||||
//init this car
|
||||
var uid = "";//todo connect to srv
|
||||
var car = require("./Car").getCar(uid);
|
||||
exports.thisCar = car;
|
||||
|
||||
//handlers for client requests
|
||||
var handle = {};
|
||||
handle["/"] = handlers.other;
|
||||
handle["/loadBin"] = handlers.loadBin;
|
||||
handle["/control"] = handlers.control;
|
||||
handle["/other"] = handlers.other;
|
||||
|
||||
//add handlers to events from udev monitor (add device and remove device)
|
||||
handle["/loadBin"] = require("./handlers/loadBinHandler").handler;
|
||||
handle["/control"] = require("./handlers/controlHandler").handler;
|
||||
handle["/route"] = require("./handlers/setRouteHandler").handler;
|
||||
exports.transportFilePath = "/dev/ttyACM0";
|
||||
//add event handlers from udev monitor (add device and remove device)
|
||||
const monitor = udev.monitor();
|
||||
monitor.on('add', function (device) {
|
||||
if (device.ID_VENDOR_ID == "0483" && device.ID_MODEL_ID == "5740" && device.SUBSYSTEM == "tty") {
|
||||
//mc connected
|
||||
console.log("connected");
|
||||
console.log("file=" + device.DEVNAME)
|
||||
console.log("connected. transport file is " + device.DEVNAME);
|
||||
exports.transportFilePath = device.DEVNAME;
|
||||
console.log(device.DEVNAME);
|
||||
}
|
||||
});
|
||||
monitor.on('remove', function (device) {
|
||||
@@ -61,6 +70,7 @@ monitor.on('remove', function (device) {
|
||||
}
|
||||
});
|
||||
|
||||
//check of exists st-flash util
|
||||
if (typeof fs.access == "function") {
|
||||
fs.access(executeShell, fs.F_OK, function (error) {
|
||||
if (!error) {
|
||||
@@ -73,4 +83,10 @@ if (typeof fs.access == "function") {
|
||||
console.log("warning: you have old version of node.js. Check existence of the file st-flash on root of server dir yourself");
|
||||
server.start(router.route, handle);
|
||||
}
|
||||
// server.start(router.route, handle);
|
||||
|
||||
//move car
|
||||
var delta = 100;
|
||||
setInterval(moveCar, delta);
|
||||
function moveCar() {
|
||||
car.move(delta)
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
},
|
||||
"author": "maxim",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"devDependencies": {
|
||||
"udev": "^0.3.0",
|
||||
"commander": "^2.9.0",
|
||||
"protobufjs": "^5.0.1"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
syntax = "proto3";
|
||||
package carkot;
|
||||
|
||||
option java_package = "proto.car";
|
||||
option java_outer_classname = "Connect";
|
||||
|
||||
message ConnectionRequest {
|
||||
string ip = 1;
|
||||
int32 port = 2;
|
||||
}
|
||||
|
||||
message ConnectionResponse {
|
||||
int32 uid = 1;
|
||||
int32 code = 2;
|
||||
string errorMsg = 3;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
syntax = "proto3";
|
||||
package carkot;
|
||||
|
||||
option java_package = "proto.car";
|
||||
option java_outer_classname = "Direction";
|
||||
|
||||
message DirectionRequest {
|
||||
enum Command {
|
||||
stop = 0;
|
||||
forward = 1;
|
||||
backward = 2;
|
||||
left = 3;
|
||||
right = 4;
|
||||
}
|
||||
Command command = 1;
|
||||
}
|
||||
|
||||
message DirectionResponse {
|
||||
int32 code = 1;
|
||||
string errorMsg = 2;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
syntax = "proto3";
|
||||
package carkot;
|
||||
|
||||
option java_package = "proto.car";
|
||||
option java_outer_classname = "Location";
|
||||
|
||||
message LocationResponse {
|
||||
|
||||
LocationData locationResponseData = 1;
|
||||
int32 code = 2;
|
||||
string errorMsg = 3;
|
||||
|
||||
message LocationData {
|
||||
double x = 1;
|
||||
double y = 2;
|
||||
double angle = 3;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@ syntax = "proto3";
|
||||
package carkot;
|
||||
|
||||
option java_package = "proto.car";
|
||||
option java_outer_classname = "RouteP";
|
||||
option java_outer_classname = "Route";
|
||||
|
||||
message Route {
|
||||
repeated WayPoint way_points = 1;
|
||||
message RouteRequest {
|
||||
repeated WayPoint way_points = 1;
|
||||
|
||||
message WayPoint {
|
||||
double distance = 2;
|
||||
@@ -13,13 +13,7 @@ message Route {
|
||||
}
|
||||
}
|
||||
|
||||
message Direction {
|
||||
enum Command {
|
||||
stop = 0;
|
||||
forward = 1;
|
||||
backward = 2;
|
||||
left = 3;
|
||||
right = 4;
|
||||
}
|
||||
Command command = 1;
|
||||
message RouteResponse {
|
||||
int32 code = 1;
|
||||
string errorMsg = 2;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
syntax = "proto3";
|
||||
package carkot;
|
||||
|
||||
option java_package = "proto.car";
|
||||
option java_outer_classname = "RouteDone";
|
||||
|
||||
message RouteDoneResponse {
|
||||
int32 code = 1;
|
||||
string errorMsg = 2;
|
||||
}
|
||||
Reference in New Issue
Block a user