[Project] Control a Crane System with Linkbot
Introduction:
Each Linkbot is a building block. Multiple Linkbots and accessories can be easily snapped together, without special tools, to create various Linkbot systems for different tasks and projects. In this project,3 Linkbot-I, 5 Linkbot-L, Cube Connectors, and other accessories are used to create a crane system. The project also demonstrates the application of the following advanced concepts: control Linkbot-L, control a group of Linkbots, write a C function, arcLength=radius*angle.
Information:
Grades: 7 – 12
Duration: 6-20 Hours
Level: Advanced (control Linkbot-L, control a group of Linkbots, write a C function, arcLength=radius*angle)
Parts Used in the Project:
3 Linkbot-I (used for the spool, gripper, and driver)
5 Linkbot-L (used for four wheels and for swivel on the top).
1 Linkbot Dongle (or another Linkbot as a Dongle)
1 4” Wheels
7 3.75” Wheels
5 Ball Casters
45 Cube Connectors (If you do not have 45 Cube Connectors, lower the height of the crane with less Cube Connectors and adjust the program accordingly).
1 Gripper Pair
94 Snap Connectors
1 Hacky Sack
1 string
Setup:
Three Linkbot-I are used for the spool, gripper, and driver. Five Linkbot-L are used for four wheels and for swivel on the top. Make sure the following setup are taken into consideration:
All Bots start zeroed
Wheel Bots start with wheel on the outside
Spool Bot starts spooled so Gripper Bot is at max height
Gripper Bot starts hanging over frontLeft Wheel Bot
Order for IDs in Linkbot Labs (top to bottom): frontLeft, frontRight, backRight, backLeft, swivel, spool, gripper, driver.
Check your number of rotations to drop the Gripper fully and modify the program accordingly, especially if less Cube Connectors are used to reduce the height of the crane.
The Linkbots used in the Crane Systemm are labeled in Figure 1. Figure 2 shows the Crane System in a different view of angle to demonstrate how parts are snap connected.
Figure 1: The configuration with Linkbot-I and Linkbot-L for the Crane System.
Figure 2: Another view of the Crane System showing how parts are Snap Connected.
Programming the dog in Ch:
A Ch program crane.ch can be used to control this Crane System. Details for each robot member function for CLinkbotI and ClinkbotL can be found in the textbook “Learning Robot Programming with Linkbot for the Absolute Beginner”. How to write a C function can be found in the textbook “Learning Computer Programming with Ch for the Absolute Beginner”. The entire PDF files for these two textbooks are available in C-STEM Studio.
/* File: crane.ch
* Crane configuration has:
* Four Wheels: frontLeft, frontRight, backLeft, backRight (Linkbot L)
* Spool (Linkbot I with spool on joint 3)
* Swivel (Linkbot L)
* Gripper (Linkbot I)
*
* Driver (Linkbot I) drives away with the hacky
*
* All Bots start zeroed
* Wheel Bots start with wheel on the outside
* Spool Bot starts spooled so Gripper Bot is at max height
* Gripper Bot starts hanging over frontLeft Wheel Bot
*
* Check your number of rotations to drop the Gripper
* fully and modify the program
*/
#include<linkbot.h>
//Order for IDs in Linkbot Labs (top to bottom):
//frontLeft, frontRight, backRight, backLeft,
//swivel, spool, gripper, driver
// wheels and swivel using Linkbot-L
CLinkbotL frontLeft, frontRight, backRight, backLeft, swivel;
// spool, gripper, driver using Linkbot-I
CLinkbotI spool, gripper, driver;
//Group the wheels
CLinkbotLGroup wheels;
wheels.addRobot(frontLeft);
wheels.addRobot(frontRight);
wheels.addRobot(backLeft);
wheels.addRobot(backRight);
//Initialize joint speeds
wheels.setJointSpeeds(80, 80, NaN);
spool.setJointSpeeds(80, NaN, 80);
swivel.setJointSpeeds(80, 80, NaN);
gripper.setJointSpeeds(80, NaN, 80);
//My number of rotations to drop the gripper
double numRotations = 1.75;
//Wheel radius of wheels at the base
double wheelRadius = 1.75;
//Calculate angle the joint should move based on angle of arc to turn
double arcAngleToWheelAngle(double arcAngle) {
double craneRadius = 8; //just a guess
double wheelRadius = 1.75;
double arcLength = craneRadius*degree2radian(arcAngle);
return radian2degree(arcLength/wheelRadius);
}
//Turns wheels back to home state
void resetWheels() {
wheels.moveJointTo(JOINT2, 0);
}
//Assuming Crane is in home state, turns wheels for movement
void initializeDriving() {
resetWheels();
frontLeft.moveJointNB(JOINT2, -45);
backLeft.moveJointNB(JOINT2, 45);
frontRight.moveJointNB(JOINT2, 45);
backRight.moveJoint(JOINT2, -45);
}
//Turns the crane in place to the right for a given angle
void turnRight(double angle) {
resetWheels();
wheels.moveJoint(JOINT1, arcAngleToWheelAngle(angle));
}
//Turning Left is the opposite of turning right
void turnLeft(double angle) {
turnRight(-1 * angle);
}
//Swivels so the Gripper moves clockwise for a given angle
void swivelCrane(double angle) {
swivel.setJointSpeed(JOINT2, 10);
swivel.moveJoint(JOINT2, -1 * angle);
}
//Turn the spool to lower the gripper a given number of rotations of the spool Bot
//TODO: function to convert numRotations to inches but that differs for each string/spool
void lowerGripper(double numRotations) {
spool.moveJoint(JOINT3, 360.0 * numRotations);
}
//Raising the Gripper is the opposite of lowering it
void raiseGripper(double numRotations) {
lowerGripper(-1.0 * numRotations);
}
//Drive forward or backward given distance in inches
void drive(double distance) {
double angleToDrive = radian2degree(distance/wheelRadius);
initializeDriving();
frontLeft.moveJointNB(JOINT1, angleToDrive);
backLeft.moveJointNB(JOINT1, angleToDrive);
frontRight.moveJointNB(JOINT1, -1 * angleToDrive);
backRight.moveJoint(JOINT1, -1 * angleToDrive);
}
//Open gripper mouth
void openMouth() {
gripper.moveJointToNB(JOINT1, -45);
gripper.moveJointTo(JOINT3, -45);
}
//Close mouth (set for Hacky)
void closeMouth() {
gripper.moveJointToNB(JOINT1, -7);
gripper.moveJointTo(JOINT3, -7);
}
void pickUp(double numRotations) {
//gripper.openGripper(40);
openMouth();
lowerGripper(numRotations);
//gripper.closeGripper();
closeMouth();
raiseGripper(numRotations);
}
drive(30);
turnRight(45);
drive(7);
swivelCrane(45);
pickUp(numRotations);
swivelCrane(30);
lowerGripper(numRotations - 0.6);
openMouth();
driver.driveDistanceNB(20, 1.75);
raiseGripper(numRotations - 0.6);
swivelCrane(-75);
closeMouth();
resetWheels();