Skip to content

Commit 306f79b

Browse files
committed
Add Robot Calibration Script
1 parent 592f668 commit 306f79b

File tree

8 files changed

+298
-63
lines changed

8 files changed

+298
-63
lines changed

software/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"temp": "~0.5.0",
2525
"request": "~2.12.0",
2626
"johnny-five": "git://github.com/rwaldron/johnny-five.git",
27-
"xmlhttprequest" : "~1.5.0"
27+
"prompt": "~0.2.14",
28+
"request": "~2.12.0"
2829
}
2930
}

software/src/calibrate.js

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#! /usr/local/bin/node
2+
3+
var prompt = require("prompt")
4+
, fs = require("fs")
5+
, eol = require('os').EOL
6+
, ArgumentParser = require('argparse').ArgumentParser
7+
, robot = require('./lib/server/robot_http_client').client("127.0.0.1","4242");
8+
9+
var args = {},
10+
newCalibrationData = {};
11+
12+
function CalibrationManager(argv) {
13+
args = argv;
14+
prompt.message = '';
15+
prompt.delimiter = '';
16+
prompt.start();
17+
}
18+
exports.CalibrationManager = CalibrationManager;
19+
20+
var getCommandLineArgs = function() {
21+
var parser = new ArgumentParser({
22+
version: '0.0.1',
23+
addHelp:true,
24+
description: 'Tapster Calibration Script'
25+
});
26+
27+
parser.addArgument(
28+
[ '-o', '--output' ], {
29+
defaultValue: "calibration.json"
30+
, help: 'file to save calibration data to'
31+
}
32+
);
33+
34+
return parser.parseArgs();
35+
};
36+
37+
CalibrationManager.prototype.calibrate = function() {
38+
robot.calibrationData(function (calibrationData) {
39+
console.log("Receiving existing calibration data.");
40+
newCalibrationData = calibrationData;
41+
console.log(newCalibrationData);
42+
var schema = {
43+
description: 'Please remove the arms from the robot and press any key to continue...',
44+
type: 'string'
45+
};
46+
prompt.get(schema, function () {
47+
calibrateServos(function () {
48+
console.log("New Calibration Data Generated.");
49+
console.log(newCalibrationData);
50+
robot.setCalibrationData(newCalibrationData, function () {
51+
console.log("Robot is now calibrated!");
52+
fs.writeFile(args.output, JSON.stringify(newCalibrationData, null, 2), function(err) {
53+
if(err) {
54+
console.log('Calibration data could not be saved: ' + err);
55+
} else {
56+
console.log('Calibration data saved to "' + args.output +'"');
57+
}
58+
});
59+
});
60+
});
61+
});
62+
});
63+
};
64+
65+
66+
var calibrateServos = function(cb) {
67+
var calibrateServoMinAndMax = function(armIndex, cb) {
68+
return robot.reset(function () {
69+
return calibrateServo(armIndex, true, function () {
70+
return calibrateServo(armIndex, false, cb);
71+
});
72+
});
73+
};
74+
return calibrateServoMinAndMax(0, function() {
75+
return calibrateServoMinAndMax(1, function() {
76+
return calibrateServoMinAndMax(2, function() {
77+
return robot.reset(cb);
78+
});
79+
});
80+
});
81+
};
82+
83+
var calibrateServo = function(armIndex, isMin, cb) {
84+
robot.angles(function (angles) {
85+
var description = 'Enter an adjustment for arm #' + (armIndex +1) + ', enter 0 when the arm is ' +
86+
(isMin ? 'parallel to the roof.' : 'perpendicular to the roof');
87+
var schema = {
88+
name: "delta",
89+
description: description,
90+
type: 'number'
91+
};
92+
93+
return prompt.get(schema, function (err, result) {
94+
if (result.delta < 0.05 && result.delta > -0.05) {
95+
newCalibrationData["servo" + (armIndex+1)][(isMin ? "min" : "max" ) + "imumAngle"] = angles[armIndex];
96+
return cb();
97+
} else {
98+
console.log("Old Angles: " + angles);
99+
angles[armIndex] = angles[armIndex] + result.delta;
100+
console.log("New Angles: " + angles);
101+
robot.setAngles(angles[0], angles[1], angles[2], function() {
102+
return calibrateServo(armIndex, isMin, cb);
103+
});
104+
}
105+
});
106+
});
107+
};
108+
109+
if(require.main === module) {
110+
new CalibrationManager(getCommandLineArgs()).calibrate();
111+
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
var fs = require("fs");
2+
3+
// default calibration
4+
module.exports.defaultData = {
5+
restPoint : {
6+
x : 0,
7+
y : 0,
8+
z : -120
9+
},
10+
servo1 : {
11+
minimumAngle : 20,
12+
maximumAngle : 90
13+
},
14+
servo2 : {
15+
minimumAngle : 20,
16+
maximumAngle : 90
17+
},
18+
servo3 : {
19+
minimumAngle : 20,
20+
maximumAngle : 90
21+
}
22+
};
23+
24+
module.exports.getDataFromFilePath = function(filePath) {
25+
if (fs.existsSync(filePath)) {
26+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
27+
} else {
28+
return null;
29+
}
30+
};
File renamed without changes.

software/src/server/robot.js renamed to software/src/lib/server/robot.js

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
var kinematics = require("./../lib/kinematics");
1+
var kinematics = require("./../kinematics");
22
var method = Robot.prototype;
33

44
function Robot(servo1, servo2, servo3, calibration) {
55
this._servo1 = servo1;
66
this._servo2 = servo2;
77
this._servo3 = servo3;
88
this._calibration = calibration;
9-
this._minAngle = 10;
10-
this._maxAngle = 20;
11-
this._range = this._maxAngle - this._minAngle;
129
this._dancer_interval = null;
1310
}
1411

@@ -68,8 +65,8 @@ method.setPosition = function(x, y, z) {
6865
this.setAngles(t1,t2,t3);
6966
};
7067

71-
method.reset = function() {
72-
this.setPosition(calibration.restPoint.x, calibration.restPoint, calibration.restPoint.z);
68+
method.resetPosition = function() {
69+
this.setPosition(this._calibration.restPoint.x, this._calibration.restPoint.y, this._calibration.restPoint.z);
7370
};
7471

7572
method.getPositionForAngles = function(t1,t2,t3) {
@@ -85,9 +82,12 @@ method.getAnglesForPosition = function(x,y,z) {
8582

8683
method.startDancing = function() {
8784
var _dance = function() {
88-
var t1 = parseInt((Math.random() * this._range) + this._minAngle, 10);
89-
var t2 = parseInt((Math.random() * this._range) + this._minAngle, 10);
90-
var t3 = parseInt((Math.random() * this._range) + this._minAngle, 10);
85+
var minAngle = 10;
86+
var maxAngle = 20;
87+
var range = maxAngle - minAngle;
88+
var t1 = parseInt((Math.random() * range) + minAngle, 10);
89+
var t2 = parseInt((Math.random() * range) + minAngle, 10);
90+
var t3 = parseInt((Math.random() * range) + minAngle, 10);
9191
this.setAngles(t1,t2,t3);
9292
}.bind(this);
9393

@@ -103,5 +103,13 @@ method.stopDancing = function() {
103103
}
104104
};
105105

106+
method.getCalibrationData = function() {
107+
return this._calibration;
108+
};
109+
110+
method.setCalibrationData = function(newData) {
111+
this._calibration = newData;
112+
};
113+
106114
module.exports = {};
107115
module.exports.Robot = Robot;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
var http = require('http');
2+
3+
exports.client = function(address, port) {
4+
var get = function(path, cb) {
5+
return http.get({ host: address, port: port, path: path }, function(res){
6+
res.setEncoding('utf8');
7+
return res.on('data', function(chunk) {
8+
var result = JSON.parse(chunk);
9+
return cb(result.data);
10+
});
11+
}).on("error", function(err){
12+
console.log("Got error: " + err.message);
13+
return cb(null, err);
14+
});
15+
};
16+
var post = function(path, bodyData, cb) {
17+
var req = http.request({ host: address, port: port, path: path, method: 'POST'}, function(res) {
18+
res.setEncoding('utf8');
19+
return res.on('data', function (chunk) {
20+
var result = JSON.parse(chunk);
21+
return cb(result.data);
22+
});
23+
}).on('error', function(err) {
24+
console.log("Got error: " + err.message);
25+
return cb(null, err);
26+
});
27+
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
28+
req.write(bodyData);
29+
req.write('\n');
30+
req.end();
31+
};
32+
return {
33+
address : address,
34+
port : port,
35+
url : function(uri) {
36+
return 'http://' + address + ":" + port + uri;
37+
},
38+
angles : function(cb) {
39+
return get('/angles', cb);
40+
},
41+
setAngles : function(theta1, theta2, theta3, cb) {
42+
var postData = "theta1=" + theta1 + "&theta2=" +theta2 + "&theta3=" + theta3;
43+
return post('/setAngles', postData, cb);
44+
},
45+
position : function(cb) {
46+
return get('/position', cb);
47+
},
48+
setPosition : function(x, y, z, cb) {
49+
var postData = "x=" + x + "&y=" + y + "&z=" + z;
50+
return post('/setPosition', postData, cb);
51+
},
52+
reset : function(cb) {
53+
return post('/reset', '', cb);
54+
},
55+
calibrationData : function(cb) {
56+
return get('/calibrationData', cb);
57+
},
58+
setCalibrationData : function(newData, cb) {
59+
var postData = "newData=" + JSON.stringify(newData);
60+
return post('/setCalibrationData', postData, cb);
61+
}
62+
/*
63+
positionForCoordinates : function(x,y) {
64+
var xmlHttp = new XMLHttpRequest();
65+
xmlHttp.open( "GET", this.url('/positionForCoordinates/x/' + x + "/y/" + y), false );
66+
xmlHttp.send( null );
67+
return eval(xmlHttp.responseText);
68+
},
69+
coordinatesForPosition : function(x,y) {
70+
var xmlHttp = new XMLHttpRequest();
71+
xmlHttp.open( "GET", this.url('/coordinatesForPosition/x/' + x + "/y/" + y), false );
72+
xmlHttp.send( null );
73+
return eval(xmlHttp.responseText);
74+
},
75+
*/
76+
/*
77+
tap : function(x,y) {
78+
var xmlHttp = new XMLHttpRequest();
79+
xmlHttp.open( "GET", this.url('/tap/x/' + x + "/y/" + y), false );
80+
xmlHttp.send( null );
81+
return xmlHttp.responseText;
82+
}*/
83+
};
84+
};

0 commit comments

Comments
 (0)