CS4610: LAB 3

In the first part of this lab you’ll assemble the manipulator arm and gripper on your robot. This arm has three rotating joints and a gripper, all actuated by Robotis AX12 “Dynamixel” robot servos (doc). These receive battery power via the org and are controlled by a serial communications interface also on the org. Monitor commands are provided (and their Java and Scheme correspondents) to move the arm and to query its state.

In the second part of the lab you’ll write high level code with the Java or Scheme interface to move the gripper to commanded locations in world frame, using the robot’s turn-in-place capability to add a fourth rotating degree-of-freedom (DoF) to the arm workspace. In the third part you will program the robot to drive towards the location of an object on the ground, deploy the arm, and grasp the object.

Robot Assembly

  1. Get your arm assembly, two shoulder blocks, mast bracket, four servos labelled 0 to 3, four servo cables, 18 4–40x5/8" screws, 6 4–40x3/8" screws, and 16 M2x8mm screws.
  2. Unscrew the four 4–40 screws that are currently holding the top plate down. Try not to shift the top plate too much. Verify that the four standoffs from which you have removed the screws are in the correct places (see demonstration).
  3. Carefully tilt up the top plate (so as not to break any wires) and remove (only) the two outer-most screws holding the rear wheel brackets.
  4. Examine the mast bracket and place it over the rear wheel brackets with the correct side down. Line up the holes and re-assemble the two screws you removed in the previous step, but this time through the holes in the mast bracket.
  5. Still being very carefull with the wires, unscrew the four screws from the underside of the top plate which are holding the electronics stack in place.
  6. Maneuver each servo into the correct place under the top plate and secure with 4 M2x8mm screws. See the demonstration to understand where each servo goes. Pay close attention: the servos have been pre-configured with ID numbers that must match their final locations on the robot.
  7. Re-attach the electronics assembly with the four screws you removed in step 5.
  8. Attach the servo cables as in the demonstration. Do not attach them to the org yet.
  9. Line up the white marks on each servo (see demonstration).
  10. Insert the shoulder blocks onto the arm shoulder shaft (if they are not there already), make sure the 4 servo belts are in place on the sprockets on the arm shoulder shaft (see demonstration), and maneuver the arm into place under the front of the top plate. Loosely hook each belt over the corresponding servo (see demonstration). Try not to rotate the servo horns.
  11. Holding the arm in a straight-out pose, attach the shoulder blocks under the top plate with one 4–40x5/8" screw each. Verify that the white marks are still approximately lined up on each servo and that the arm is approximately pointing straight forward (have someone hold the arm in this pose). Then add three more 4–40x5/8" screw to each shoulder block.
  12. Re-attach the top plate with the four screws you removed in step 2.
  13. Assemble 4 4–40x3/8" and 2 4–40x5/8" screws through the top plate into the mast bracket.
  14. Carefully set the robot on its side and add two 4–40x3/8" screws through the bottom plate into the mast bracket and 8 4–40x5/8" screws into the shoulder brackets.
  15. Have the course staff check your work, then connect the servo chain to the org with the cable dangling from servo 1.

The Lab Tarball

We have prepared an archive file of sourcecode that you’ll use in this lab. Follow similar instructions as for lab 0 to download and unpack it (on the panda). Make sure that the unpacked lab3 directory is a sibling to your existing lab?directories that were unpacked from the prior lab tarballs.

If you are running the panda headless, use the following command to download a copy of the lab tarball:

> wget http://www.ccs.neu.edu/course/cs4610/LAB3/lab3.tar.gz

We ask you not to modify the files you unpack from the lab tarball. You will write code that refers to these files and that links to their generated libraries. Please do not work directly in the provided files, in part because we will likely be posting updates to the lab tarball.

  1. In lab3/src/org/libpololu-avr run make to build the Pololu AVR library.
  2. In lab3/src/org/monitor run

    > make
    > make program
    
    to build the OHMM monitor and flash the new monitor code to the org.
  3. In lab3/src/host/ohmm run

    > make
    > make jar
    
    to build OHMM.jar. (In the event that we distribute an updated lab tarball, you will need to re-make in org/libpololu-avr, org/monitor, and host/ohmm, re-program in org/monitor, and re-jar in host/ohmm.)
  4. Runing

    > make project-javadoc
    

    in lab3/src/host/ohmm will generate documentation for the OHMM Java library in lab3/src/host/ohmm/javadoc-OHMM (the top level file is index.html); or you can view it online here.

The lab 3 monitor program includes a set of ax* commands to interact directly with the AX12 servos (documented in monitor/ohmm/ax12.h). It also includes a set of a* commands to interact with the servos in the context of the OHMM manipulator arm (documented in monitor/ohmm/arm.h). It is strongly recommended to use only the higher-level arm commands except for debugging purposes.

The Java OHMM library and the Scheme OHMMShell also provide access to the AX12 and arm module commands.

You may wish to review the instructions in lab 2 on how to run OHMMShell and how to compile your own Java code against OHMM.jar.

Prepare Your SVN Repository

  1. Follow similar instructions as for lab 2 to make a checkout of your group svn repository on your panda as a sibling directory to the lab3 directory you unpacked from the lab tarball.

  2. Change directory so that you are in the base directory of your svn repository checkout (i.e. you are in the g? root directory of the svn checkout), then run the commands

    > mkdir lab3
    > d=../lab3/src/host/ohmm
    > cp $d/makefile $d/run-class ./lab3/
    > cp $d/makefile-lab ./lab3/makefile.project
    > sed -e "s/package ohmm/package lab3/" < $d/OHMMShellDemo.java > ./lab3/OHMMShellDemo.java
    > svn add lab3
    > svn commit -m "added lab3 skeleton"
    

    This sets up the directory g?/lab3 in the SVN repository in which you will write all code for this lab. The makefile should not need to be modified: it is pre-configured to find the OHMM Interface library in ../../lab3/src/host/ohmm. It also will automatically compile all .java files you create in the same directory.

Arm Testing and Calibration

  1. Bring up an OHMMShell and run the following commands to enable the arm and send it to the calibration pose:

    > (ae #t)
    > (ac)
    
  2. The calibration pose is intended to have the arm pointing straight forward with the gripper closed. Since you were directed above to assemble the arm in this pose while the servos were at the middle of their range of motion (with the white marks lined up), in theory this pose should be reached by setting each servo to the goal position 512 in AX12 counts (the AX12 servos have a range of motion of 0 to 300 degrees, with 0 degrees corresponding to 0 counts and 300 degrees corresponding to 1023 counts). However, various sources of error will cause each arm to reach a slightly different pose when all servos are commanded to 512.

    Very carefully using commands like

    > (axsg i c)
    

    where i is a servo index (0 = shoulder, 1 = elbow, 2 = wrist, 3 = gripper) and c is the goal counts (start with 512 and work in increments of about +/- 10 counts at a time), try to adjust your arm so that it appears to be in the correct straight-forward calibration pose. You may also judiciously tension the gripper to close with a little bit of force here. Try adding and subtracting 10 counts from the gripper servo first to understand which direction closes and which direction opens the gripper. Then open the gripper to a small gap, followed by closing it in small increments until the fingers are just touching. Continue closing by 10 or 20 further counts to tension the gripper a bit. (Note: the gripper state actually is set by the difference between servos 2 and 3, so you may also need to fiddle with servo 2 to maintain the calibration pose.)

  3. Once you are satisfied with the calibration, read out the current goal locations of each servo:

    > (axrd16 0 ax-goal-position)
    > (axrd16 1 ax-goal-position)
    > (axrd16 2 ax-goal-position)
    > (axrd16 3 ax-goal-position)
    
  4. Record the values on paper as c0, c1, c2, c3. Then set them as the new arm calibration values like this:

    > (asac c0 c1 c2 c3)
    

    where you substitue the actual numbers for each calibration value. The arm should not move when you do this, but if you then test the calibration by running

    > (ah)
    > (ac)
    

    the arm should move to the home pose and then back to the correct calibration pose. The calibration values will be stored on the org in nonvolatile EEPROM so so that you should not have to re-calibrate unless you re-flash the org (in which case the EEPROM will be erased).

Inverse Kinematics

Using the inverse kinematics method of your choice, implement a program that runs on the panda (this is a requirement), homes the arm, and then responds to keypresses as follows, with initially:

w — move the gripper +mm in the world-frame direction
s — move the gripper -mm in the world-frame direction
a — move the gripper +mm in the world-frame direction
d — move the gripper -mm in the world-frame direction
r — move the gripper +mm in the world-frame direction
f — move the gripper -mm in the world-frame direction
q
z

Assume that the robot is at world frame pose initially. Use turn-in-place wheel motions (only) to add a “yaw” DoF to the arm kinematics. Use the wrist DoF to keep the gripper horizontal (parallel to the ground, as it is in arm home pose) at all times.

If the target location is not reachable, your program must emit a message. However, it is up to you to decide how to move the arm in the case of unreachable targets. For example, you could make a best-effort motion to reach towards the target. However you do it, you must maintain the following property: any sequence of keypresses followed by the reverse sequence, e.g. “wwrrffss”, must return the arm to the home pose. This effectively establishes the set of possible target points as a rectilinear lattice centered at the gripper location in home pose and axis-aligned in world frame.

You may find that reading a single keypress from the console is not easy in Java; in fact, technically, it’s not possible to do in a portable way using the current standard Java API. However, here we will accept a solution which runs on Unix; for that see the provided code in ohmm.ConsoleNonblocking. Alternatively, we will accept solutions which open a graphics window and then respond to KeyEvents there.

The notes for Lecture 9 give details of the arm kinematics, including the link lengths. They also present an analytic IK approach for this arm.

Grasping

Retrieving objects on the ground is a common task in mobile manipulation. In this part, you will implement a basic method to approach an object, grasp it, and carry it.

  1. Fashion a small object from paper. The object should sit on the ground and have a narrow upwards protrusion tall enough so that the gripper can engage it when lowered to within 5mm of ground clearance. You may want to have the protrusion expand a bit at its top to help prevent the object slipping out of the gripper.

  2. Using your horizontal-gripper IK solution from above, write a program to produce a yaw-free grasp sequence starting from home pose:

    1. open the gripper
    2. lower the arm with a interpolation to within 5mm ground clearance
    3. move the arm forward with a robot-frame interpolation by an amount you determine
    4. close the gripper
    5. return to home pose.

    The robot chassis should remain in place at all times. Calculate the robot frame offset distance from the robot frame origin where an object on the ground should be grippable at step d. Practice picking up the object; tune the sequence as you see fit to maximize grip success.

  3. Extend your program so that it can take the coordinates of the object on the ground as command line arguments in world frame millimeters (if no command line arguments are given, then the program should revert to keyboard control inverse kinematics as above). For example, if your Java class to solve this part is called Grasp, you should be able to invoke it like this

    > ./run-class Grasp 30 40
    

    for a goal at mm in world frame. Assuming the robot starts at pose in world frame, have your program

    1. home the arm
    2. turn towards the object
    3. drive straight until it is within a radius (the above-determined offset distance) from the object
    4. stop
    5. engage your gripping sequence to acquire the object
    6. return home to the world frame pose (keeping the arm in its home pose)

Note: you may need to re-calibrate the robot wheel-to-wheel baseline distance to improve the accuracy of turn-in-place motions. You may optionally take a third command line parameter giving the robot baseline distance in mm (thus allowing it to be adjusted at the beginning of each run).

Grading

You will be asked to demonstrate your code for the course staff in lab on the due date for this assignment. We will try out code; 30% of your grade for the lab will be based on the observed behavior. Mainly want to see that your code works and is as bug-free as possible.

The remaining 70% of your grade will be based on your code, which you will hand in following the instructions on the assignments page by 11:59pm on the due date for this assignment. We will consider the code completeness, lack of bugs, architecture and organization, documentation, syntactic style, and efficiency, in that order of priority. You must also clearly document, both in your README and in code comments, the contributions of each group member. We want to see roughly equal contributions from each member. If so, the same grade will be assigned to all group members. If not, we will adjust the grades accordingly.