GRRC Technical Report 2010-02 Dynamic Simulation and Collision Modeling of the Packbot Manipulator Author: John Hall Supervisor: Joshua Langsfeld Advisors: Prof. Dawn Tilbury Prof. Ella Atkins Date of completion: August 11, 2010 UNCLASSIFIED: Dist. A. Approved for public release Table of Contents 1 Introduction.……………………………………………………………………….……... 3 2 The Goal…………………………………………………………………………….……. 3 3 Modeling…………………………………………………………………………….…… 3 3.1 Geometry and Kinematics………………………………………………….…..... 3 3.2 Dynamic Modeling………………………………………………………….…… 4 3.3 Collision Detection………………………………………………………….…… 4 3.4 Collision Behavior and Simulation…..…………………….……………….……. 5 4 Results……………………………………………………………………………………..7 5 Future Work………………………………………………………………………….…... 8 6 Summary………………………………………………………………………….……… 8 7 References………………………………………………………………………..………. 9 8 Appendix A: Details and Limitations of the SolidWorks Model……………………..…10 9 Appendix B: Notes on Collision Detection Implementation…………………………… 11 10 9.1 Basic Concepts………………………………………………………………….. 11 9.2 Speed Concerns…………………………………………………………………. 12 Appendix C: Code Documentation…..…………………………………………………..13 10.1 Data Storage and Indexing……………….……………………………………... 13 10.2 Calling Structure………...……………………………………………………… 15 10.3 Function Overviews…………………………………………………………….. 15 10.4 Known Issues………………………………………………………………….…22 2 1 Introduction The Packbot is a ground robot commonly used by the US military for explosive ordnance disposal. It is prone to failure in the field for various reasons [1]. When a single joint of the Packbot EOD manipulator fails, the entire arm is rendered useless despite the fact that it has redundant degrees of freedom. We are designing reconfigurable control systems and strategies to regain manipulator function in the face of joint failure, but we lack any way to test these strategies. Either a copy of the arm or a software model is needed, and this report describes the software route. 2 The Goal The purpose of this research project is to model of the physical behavior of the Packbot EOD arm in order to enable the design of reconfigurable control systems. The behavior described in the robot dynamic equations is important, as are the contact forces between the links of the robot and its static environment. A complete model will include kinematics, dynamics, and collision physics. Such a model will allow us to study failures in the Packbot arm without a physical example of the arm. This report describes efforts to study and model the Packbot arm and the development of virtual tools to aid this and future studies of the Packbot. 3 Modeling Initial work on control reconfiguration of the Packbot manipulator can be divided into three tasks: describing the geometry and kinematics of the real Packbot arm with software tools, creating dynamic models to predict the behavior of the arm, and using these dynamic models to simulate failures and new control schemes. 3.1 Geometry and Kinematics SolidWorks was used to create a visual and geometric model of the Packbot, shown here. This model is based on length measurements taken by hand. Because the measurements were taken by hand, the accuracy uncertainty is noticeable. Detailed notes on the model’s fidelity may be found in Appendix A. The focus in creating this model was to define the manipulator enough to accurately determine its Denavit-Hartenberg (DH) parameters. These parameters can be used to fully describe the kinematic behavior of the manipulator. Each link of the arm is also designed to have inertial properties similar to the actual link. Each of the first two major links is represented by a hollow tube encasing a computer chip and a Figure 1: SolidWorks model 3 motor. The ends are capped with solid parts meant to represent the joint casing and gearings. The third major link has, like the first two, a tube containing a chip. The gripper wrist and the camera wrist are described as solid objects. The motors in this link are assumed to be contained in the wrist parts. Each CAD part is considered to be uniform in density, but since the mass and location of each object in the link is true to reality, the overall inertia and center of mass for each link should be relatively accurate. Since SolidWorks is ill-suited to kinematic analysis, a MATLAB model was created using the geometry of the first model as a reference. Specifically, we used the MATLAB Robotics Toolbox [2] created by Peter Corke to make this model. In addition to describing the kinematics of serial-link manipulators, the toolbox also includes features for dynamic analysis. 3.2 Dynamic Modeling While kinematics is useful for studying the workspace of the manipulator and for mathematically describing its movement, a dynamic model is needed to simulate mechanical behavior, like forces and inertia. We used SolidWorks to calculate the inertia and center of mass of each link. Information about the mass data may be found in Appendix A. iRobot provided the gear ratios for each of the arm joints. All this data applies to the behavior of the normal arm, but we are also interested in the behavior of a failed arm. Two common types of electromechanical failure in the manipulator are a frozen joint and a loose joint (that cannot exert any torque). A loose joint is modeled easily by restricting the torque exerted by that joint to zero. We modeled a frozen joint by redefining the arm as a five-link manipulator, with the two links connected by the frozen joint considered to be one link. For the frozen joint case, the new DH parameters are geometrically calculated, but the inertial Figure 2: MATLAB dynamic model with colliding joints properties of the combined link are interpolated across all possible joint angles. We used this more complicated method – instead of simply restricting the proper joint variable – in order to simplify the design of the reconfigurable control system. For kinematic analysis this extra calculation is not needed. 3.3 Collision Detection The normal interactions of the links (at the joints) are described by the dynamic and kinematic models, but it is also possible for the movement of the links to be restricted by interference with each other, the Packbot chassis, or the environment. To prevent physical impossibilities like intersecting solid bodies and 4 to model the reaction forces due to any collision between the solid bodies in the model, collision detection software is needed. Our collision detection algorithm approximates each solid body as a combination of convex polyhedra, as shown in Figure 3 below. This approach not only follows the real geometry of the Packbot very closely, but also allows the algorithm to use simpler and more robust geometric computations. The algorithm uses the Gilbert-Johnson-Keerthi (GJK) algorithm as a basic primitive test for collision between two polyhedra, and this method would not be valid for concave polyhedra. The GJK algorithm is described in Christer Ericson’s book [3], as well as in his presentation to SIGGRAPH 2004 [5]. To prune out unnecessary primitive tests and streamline the collision detection code as much as possible, we also implemented a bounding volume hierarchy. This works by enclosing certain combinations of polyhedra (all those in a given link, in this case) in a virtual box. By testing all these boxes against each other before testing the more complicated geometries, the number of primitive tests required decreases dramatically. Most of this code is written in MATLAB so that it meshes well with the other components of the models and is easy to edit. MATLAB is an interpreted language, however, and as such can be fairly slow. Speed is a major problem because the geometric tests include many ifstatements and loops, both of which run slowly in MATLAB. In order to speed things up, as many loops and conditional statements as possible were coded in C++ and compiled as MATLAB executables (MEX files). These are called from the MATLAB command line, but run much faster than an equivalent m-file. More details concerning the collision detection software may be found in Appendix B. 3.4 Collision Behavior and Simulation But detecting the collisions is only solves half the problem; a useful simulation will not only detect collisions but react to them. Our dynamic simulator Figure 3: Packbot approximated by polyhedra (collisionDynamics.m) implements ode45 with event detection. An event function runs at every solver step and halts execution if any of the polyhedra described in the previous section intersect. Based on which bodies are colliding, the simulation resets certain joint velocities to reflect the impact and limits the acceleration of those joints as long as the colliding bodies are in contact. The joints that represent degrees of freedom between two colliding polyhedra will be called the ‘relevant joints’ in this report. The main drawback to this joint-based algorithm is that if there is more than one degree of freedom between the colliding bodies the algorithm cannot tell which combination of those degrees of freedom caused the collision. Mathematically speaking, these positions of the relevant joints represent a space of 5 joint positions, and our current algorithm cannot calculate which subset of that space to avoid. Therefore it constrains every joint in that space in one direction based on joint velocities at the time of the collision. This works in most cases, but a more rigorous algorithm would limit movement in the joint space only along the basis vector normal to the surface (in the joint space) defined by the collision. In rare cases, using joint velocities to decide the direction in which to limit acceleration also gives an erroneous result. For instance, consider a collision with two relevant joints. The net movement from these two degrees of freedom is obviously towards collision, but it is possible that one joint was not contributing to this movement; the movement of the second joint was simply overwhelming the effect of the first. Using joint velocities to determine a direction in which to limit acceleration would result in constraining the first joint in the wrong direction. Another method we tried before using the above solution was to calculate joint torques that affect the arm in the same way Cartesian impact forces would. This method does not use the joint velocities at the time of collision, but it requires a minimum norm vector between the two colliding polyhedra. This method circumvents both major difficulties associated a purely joint space method while introducing three more problems, each of which is arguably larger. First, the using torques to create collision behavior means using large, discontinuous torque inputs to mimic impacts, and the solver will drastically decrease its step size to deal with the new stiffness in the problem. Detailed explanations for this behavior may be found in the first two sections of Appendix B. Second, the torques would be calculated from an impact force that should depend on many factors, including gravity, coriolis and centripetal forces, inertia and any disturbances or control inputs. These calculations are so complex that understanding and checking one force at one step by hand could take hours, and any mistake could cause the objects to pass through each other or rebound with excessive velocity. The third major problem with involves the direction of the force rather than its magnitude. The direction should be found from a normal vector at a point of tangency, where the polyhedra intersect but do not overlap. It is impossible to find that extremely specific time and state with no numerical error. Instead, the algorithm would use a vector of minimum norm in a non-intersecting state. The polyhedra that make up the arm model are geometric approximations that could lead to large, chaotic discrepancies in this vector between similar time steps, as shown below. Figure 5: Error in vector of minimum norm due to approximation of smooth geometry (green line is the correct vector, red line is the erroneous one) 6 All these issues considered along with development time, using the relatively simple method described in the first paragraph provides the most realistic behavior in a reasonable time frame. 4 Results This section describes one of the scenarios used to test our simulation. All joint torques are set to zero, simulating a total collapse of the arm. The initial position is the standard drive position, which is shown in Figure 6, and all initial joint velocities are zero. Using only the dynamic model and the simulator provided in the Robotics Toolbox, the arm falls through the chassis and continues to swing chaotically. A snapshot is shown in Figure 7. Figure 6: Drive Position Figure 7: Result without collision detection Figure 8: Static result with collision detection In contrast, using the simulator we have written for collision dynamics yields an intuitive static result, pictured in Figure 8. The third link remains upright because it is longer than the second link and thus becomes propped up on the shoulder joint casing. Graphs of joint position and velocity over time verify our result is static; these graphs may be found below in Figures 9 and 10. Figure 9: Planar joint positions Figure 10: Planar joint velocities 7 5 Future Work Before control simulations can be run, however, the models need to be refined to more accurately reflect real-world behavior. For instance, the effects of motor inertia and frictional forces (both static and viscous) should be added to the dynamic model. These parameters will be deduced from publicly available specifications of the maximum weight the manipulator can support. Torque limits would also serve to make simulations more realistic, although torque can be checked with a post-processor. Unfortunately, these torque limits are not publicly available, and so we will need to either negotiate the information from iRobot or deduce approximations from what specifications are publically available. The next step in making the model realistic is to design a more intelligent joint constraint algorithm. One option is to keep the current algorithm but give it the ability to self-diagnosis faults. Misbehavior of the collision code can be detected by watching for secondary intersections – intersections that occur between two bodies that are already constrained. Another option is to calculate the Jacobian matrix that describes the relationship between Cartesian space and the space of relevant joints. Taking the inverse of the Jacobian and identifying the subset of joint space that is responsible for the collision would allow us to limit motion in that direction without completely constraining every relevant joint. Whether or not we implement a more intelligent joint constraint algorithm, we will simulate dynamic transitions between failed equilibrium poses and other control challenges. The results of this research should allow us to design a reconfigurable controller that can recover function in a damaged manipulator arm. The implementation of such a controller would improve the reliability of the Packbot by mitigating the effect of failure in the field. This is the most important work that remains to be done. Another possible use of the collision software is to detect camera occlusion. If the function to be recovered from the arm is the camera’s ability to see a target, creating long, thin polytopes between the camera and its target could allow us to test whether the camera’s view is blocked. 6 Summary In order to improve the reliability of the Packbot manipulator through control reconfiguration, we have created various computer models of the manipulator. The kinematic models created in SolidWorks and MATLAB describe the geometry, position, and velocity of the arm. The kinematic model forms the basis for a dynamic model that can describe forces and collisions – the real behavior of the arm. This dynamic model will be used to formulate and test new control strategies with the goal of recovering function from a failed arm. This reconfigurable control system could improve the reliability of the Packbot by preventing minor failures from affecting the success of a mission. But there is still more to do in refining the models should more realistic behavior prove necessary. Torque limits and the effects of motor inertia and friction should be represented in the models. Also, the algorithms that determine collision behavior could be refined to work in all cases instead of just most of 8 them. These changes, especially the second one, would take time but could vastly improve the model’s usefulness in control design. 7 References [1] Phuoc-Nguyen Nguyen-Huu, Joshua Titus, “Reliability and Failure in Unmanned Ground Vehicle (UGV)”, GRRC Technical Report 2009-01, 2009. [2] Peter I. Corke, “A Robotics Toolbox for MATLAB”, IEEE Robotics and Automation Magazine, Vol. 3, March 1996. [3] Christer Ericson, Real-Time Collision Detection. Morgan Kaufmann, 2005. [4] John Nagle. “Re: Collision points with SOLID.” comp.graphics.algorithms usenet newsgroup article, Message-ID <3C4089BC.80907@animats.com>. January 12, 2002. http://groups.google.com/groups?selm=3C4089BC.80907%40animats.com [5] Christer Ericson (2004). “The Gilbert-Johnson-Keerthi (GJK) Algorithm”, SIGGRAPH. [6] “MATLAB – Documentation”, The Mathworks, 2010. http://www.mathworks.com/access/helpdesk/help/techdoc/ 9 8 APPENDIX A: Details and limitations of the SolidWorks model The following dimensions are known to within 5 mm: • full length definition of the chassis • wheel width, radius, and location • location of the arm with respect to the chassis • camera dimensions • manipulator link lengths, offsets, and diameters • joint casing diameters • wrist lengths and widths • full length dimension of the arm attachment plate These dimensions are based on estimates and memory: • motor length • computer chip width and thickness • hollow tube thickness • wrist thickness The masses of these parts are known to within 100 g: • motors • joint casing/gearings • overall arm • camera • camera wrist • end effector wrist • arm attachment plate • overall robot The masses of these parts are based on estimates and memory: • computer chips • hollow tubes • wheels • chassis 10 • 9 APPENDIX B: Notes on Collision Detection Implementation This Appendix is meant to provide notes on the collision detection software described in Sections 3.3 and 3.4. The collision detection software is a collection of MATLAB and C++ code meant to work with the MATLAB Robotics Toolbox [2]. Currently the code is specific to the Packbot, though I may generalize it at some later date. This version of the collision software only models the interactions between the links of the packbot and between the arm and its static environment. The simulation cannot yet handle external moving objects, though there is a possibility that such functionality will be added in the future. 9.1 Basic Concepts Primitive Tests The basic way to tell if objects in an environment are colliding is to test each shape in the model against every other shape for collision status and distance. Whatever test that is used is called the primitive test. In this package, the shape of the manipulator is approximated by a collection of convex polygons, and the primitive test used is the Gilbert-Johnson-Keerthi (GJK) algorithm. GJK works by iterating through different simplicies formed from the vertices of the Minkowski difference of the two polyhedra. The Minkowski difference is a set of points with the property that a convex hull of these points will include the origin if and only if the polyhedra are colliding. At each recursive step, GJK calculates the point on the current simplex that is closest to the origin. Any points in the simplex on which this closest point does not depend are removed from the simplex. Then GJK multiplies the position vector of the closest point by negative one, and determines the supporting vertex of the Minkowski difference polytope in that direction. The supporting vertex is then added to the current simplex, and the process repeats. The recursion ends if the closest point on the simplex is the origin (the polyhedra intersect), or if the supporting vertex of the Minkowski polytope is no closer to the origin than the closest point found in that recursive step (the polyhedra don’t intersect). This method converges asymptotically. Bounding Volume Hierarchy Even as fast as GJK converges, any collision detection code that simply tests each convex polyhedron against every other will be fairly slow. There are just too many primitive tests. One solution to this problem is to prune tests from the algorithm using a bounding volume hierarchy. The basic idea is to create simple shapes that contain certain combinations of the main set of polyhedra. With the Packbot manipulator, boxes fit well over the polyhedra defining each link. If a given pair of these bounding volumes do not collide, then none of the polyhedra contained in the first box collide with any of the polyhedra in the second box. This concept is used to prune tests from the collision detection algorithm. Variable-step Numerical Solvers 11 All of the ordinary differential equation (ode) solvers that come with Matlab are variable-step. This means that instead of holding a time step constant, the solver controls error by varying step size. At each step the solver estimates both the absolute error accumulated and the error relative to the last step. If either is above a specified tolerance, the solver throws out that step and calculates a new one with a smaller time increment. This continues until the error is within tolerance. Using a variable-step solver usually guarantees that the solver has not missed any high-frequency behavior, but it does cause the step size to become very small during such behavior. Stiffness Stiffness is a property of differential equations that has never been clearly defined. A problem or set of equations is considered stiff if either numerical errors or high-frequency behavior cause a numerical solver to diverge or become unstable. An example would be a trigonometric function operating at 10kHz if the solver used has a fixed step greater than around 2e-6 to 5e-6 seconds. Even such a small fixed step would ignore the function’s high-frequency behavior, causing the solver solution to diverge in most cases. A variable-step solver applied to the same problem would be forced to use a very small step size that may be undesirable if low-frequency behavior is also of interest. 9.2 Speed Concerns Computational geometry is not MATLAB’s strong suit, but it does provide excellent high-level programming features. In this package as many computing bottlenecks as possible have been replaced by C++ MEX files. In this way we hope to balance speed of computation with MATLAB’s interface. The most important use of MEX files is in gjksubmex.m. We attempted to implement the GJK algorithm purely in C++, but the main WHILE loop (GJK is recursive) caused memory problems. So instead of pure C++ code, gjksubmex.m is a MATLAB function that calls MEX files to do most of its heavy lifting. With this MEX code gjksubmex.m can run in a fraction of a millisecond. The collision physics of a robotic arm represent a stiff problem. The standard dynamics operate on a much longer time scale than the collisions, which can require bodies to change velocity very quickly. When the solver encounters an impact it drastically reduces the step size so as to stay within its error tolerance. Even a relatively large error tolerance will cause this reduction in step size; an error of 10% is still small compared to a change in sign (a change of at least -100%). The result is that a simulation scaled in seconds is run with microsecond step sizes, and even a streamlined code can take hours to finish. The solution is to separate the high- and low-frequency behavior with an event detector. Matlab solvers allow a user to specify an event function that runs at each step and can halt the solver’s integration if it detects high-frequency behavior. In this software package, the event function halts execution when it encounters a new collision state. The pertinent velocities are changed, and the solver is restarted with the new initial values. The solver will still decrease the step size immediately before the collision so that it can pinpoint the time and state at which the collision occurs, but resetting the integration also resets the step size. Thus event detection preserves both accuracy and a normal step size for this stiff problem. 12 10: APPENDIX C: Code Documentation This appendix is meant as a reference guide for the Matlab and MEX code I have written. It explains how critical data is stored and how each function works, outlines the parent/child relationships between functions, and documents known issues or problems with the current version of the code. Anyone using this software package should have MATLAB 7.6 or later and the MATLAB Robotics Toolbox Release 8 or later. The C++ source files are meant to be compiled as MEX files using the MATLAB command line. There is a script – described below – that is meant to automate this setup procedure. It is available on the GRRC-RA4 C-Tools site in the Resources section as a ZIP file. There is very little exception handling in the code as it stands now. This means that the MATLAB scripts will throw random errors if given the wrong input, and the MEX files will probably throw segmentation faults. These are bad, so check this Appendix, the release notes in the ZIP file, or the comments at the top of most functions before using them. 10.1 Data Storage and Indexing This is a description of each important data variable used as an input or output to one of the functions in Section 9.3 above. A ‘.mat’ suffix indicates a variable that is included in the collision detection package. Each of the others is the result of a function. polyhedra.mat – This is a data structure containing cross-referenced and indexed data on the verticies of polyhedra, specifically those used to represent physical bodies in this software package. The collision package includes a version of this variable for the Packbot EOD arm. Different instances of polyhedra can be made using the createCollisionBodies function. .points – This field is an nx3 matrix containing the vertices of all the polyhedra in the model. The vertices are listed first by order of the reference frame to which that polyhedron is attached and second by the individual polyhedron. All points are given with respect to the local frame of reference – that is, with respect to the frame they are attached to. .pointBody – This field is a vector length n that gives the body number of each point in the points field. Bodies are numbered within each frame, so both Frame 1 and Frame 2 have a Body 1. A number independent of frame can be obtained from the location of the body’s index in the field bodyIndex. .pointFrame – An n length vector giving the frame number each row in the points field is expressed in and attached to. .bodyIndex – An m length vector in which each element gives the row index for the beginning of a polyhedron in the points field. All indices are given in the order they appear in that 13 field. The last element is the index for the first empty row (where the next polyhedron would be if there was one). .bodyFrame – An m length vector giving the frame number for each entry of bodyIndex. .frameIndex – A vector length p that gives the indices for the beginning of each reference frame in bodyIndex, in the same way that bodyIndex gives the beginning of each polyhedron in the points field. As before, the indices are sorted in ascending order and the last index gives the first empty element in bodyIndex. .boundingBox – An (8(p-1))x3 matrix containing the vertices of all the bounding boxes calculated by boundBox.m. The format is identical to that of the points field. The fact that each box has the same number vertices, and each reference frame contains only one box, means that the extensive cross-referencing used for the original polyhedra is not necessary here. .boundingBoxIndex – This field serves the same purpose for boundingBox as bodyIndex serves for the points field, and works in the same way. It is a vector length 8(p-1). .boundingBoxFrame – An analog of bodyFrame for boundingBoxIndex that gives the frame number of each bounding box. It has the same length as boundingBoxIndex. collisions – This data structure is a global variable internal to collisionDynamics and its child functions cdyn2 and intersection. It contains data about each collision detected by the simulation that is still affecting the behavior of the arm. These are considered the active collisions. Data is written by intersection and read mostly by intersection and cydn2. .c – A vector of Boolean values, one for each active collision. An entry reads true if the two polyhedra involved are currently colliding. .bodies – A matrix with a row for each active collision. Each row is four elements – two pairs. Each pair is associated with one of the colliding polyhedra, giving the first and last body indicies into the points field from polyhedra.mat. .frames – A matrix containing the frame numbers of each polyhedron involved in an active collision. Each active collision has a row length 2, with each entry giving the frame of one of the polyhedra. .proximity – A vector with an entry for each collision that gives the smallest distance between the two polyhedra. .time – A vector the contains the simulation time at which each collision was recorded as active. .joints – A vector of variable length that lists the joints that should have their accelerations restricted by cdyn2. 14 .direction – A vector the same length as the joints field that dictates the direction in which acceleration is not allowed for each restricted joint. Each entry is -1 or 1. 10.2 Calling Structure This outline shows which functions call which others. It is only intended to give an idea of how each function relates to the others. Full descriptions are provided in the next section. • • • • • • makeCollision.m createCollisionBodies.m o boundBox.m initializeCollision o define_packbotv3.m collisionDynamics.m o cdyn2.m taufun.m o intersection.m collisionCheck.m • ptfkin.m • gjksubmex.m o PtMinNorm.mexw32 o IndexandSupport.mexw32 findRelevantJoints.m wireAnimate.m o wireplot.m Rmatrix.m 10.3 Function Overviews Below are detailed descriptions and notes on each finished function from Section 9.3 in the order they appeared in that section. Variable names are given in the Input and Output fields; sometimes these are figures created in MATLAB. Figures numbers do not refer to figures in this report; rather they give the figure window in which the output will appear. makeCollision.m Script – no input or output arguments Algorithm: This script compiles the all the MEX code needed to run collisionDynamics. It also rearranges several files for convenience after you first download the collision package. 15 Notes: Place this script in the same directory as both the collision and robot directories, and then run it. It will ask you to choose a compiler first. You may have to try one or two of these because certain compilers cannot handle MEX code. createCollisionBodies.m Input: Robot object Output: polyhedra Algorithm: This function iterates through each frame, asking the user to identify which workspace variables hold the points to define the polyhedron for each body. The user should create these variables beforehand. As it goes, it cross-references the data and stores this indexing data in the proper fields of polyhedra. When all bodies are created, createCollisionBodies will run boundBox to create bounding volumes around the bodies of each reference frame. Notes: I highly recommend using this function to create polyhedra data structures rather than assigning everything manually. It will save time and ensure that all indexing and crossreferencing is done correctly. boundBox.m Input: Output: polyhedra polyhedra Algorithm: This function iterates through each reference frame. At each frame, the function finds the maximum and minimum values in each Cartesian dimension. It uses these to determine the vertices of a box containing all bodies attached to that reference frame. Notes: This function is not very streamlined, but doesn’t need to be. It only runs once: at the end of createCollisionBodies. initializeCollision.m Script – no input or output arguments Algorithm: Adds paths to the collision and robot directories, as well as the simulink and mex directories within robot. It will then run define_packbotv3 to create a dynamic model of the Packbot EOD arm, load polyhedra.mat, and set the joint variables q to put the EOD arm in the standard drive pose. Notes: This script was meant solely for my convenience and I encourage users to alter it for theirs. It’s stored in the collision directory until you run makeCollision, which moves it outside to the parent directory. 16 define_packbotv3.m Script – no input or output arguments Algorithm: This script creates the robot and link objects for a complete dynamic model of the Packbot EOD manipulator. Most parameters in this version are approximate, but close enough to give good general results. See the Robot Toolbox guide for further information. Notes: none collisionDynamics.m Inputs: Robot object, Initial time (t0), Final time (t1), Function handle for a user-defined torque function (torqfun), Initial joint positions and velocities (q0, qd0), polyhedra, any other variables the user would like passed to the torque function Outputs: Time vector (tout), Joint position and velocity results arranged in rows by time step (qout, qdout), Event times (tcout), Joint positions and velocities at event times (qcout, qdcout) Algorithm: This function is the main simulation loop for a collision dynamics simulation. Initialization includes creating the data structure collisions as a global variable and creating an ode options structure that alters error tolerances and sets intersection.m as the events function. The simulation loop runs ode45 to solve the robot dynamic equations. The simulation will terminate early if a collision event is detected. If this happens, the initial values will reset to the time step before the collision, but with the velocities of all joints relevant to the collision set to zero. The solver will then be called again to continue solving the robot equations. This loop will continue until the simulation time has reached the final value given by the user. The global variable collisions is cleared before collisionDynamics terminates. Notes: This function replaces fdyn from the Robot Toolbox as a dynamic simulation function and wrapper for ode45. The torque function serves the same purpose as before, and the outputs are formatted similarly. The main differences are the event detection features and the addition of polyhedra as a required input. As in fdyn, extra arguments will be passed through to the torque function. When an event occurs and the solver terminates, the joint velocities relevant to the collision do not have to be set to zero. This represents only the perfectly inelastic case. Multiplying the velocities by a coefficient of elasticity will yield any sort of collisions the user desires. However, the simulation will break if the sign of the velocity is not reversed in the more elastic case. The user is encouraged to tweak the error tolerances to ensure a reasonable run time. This function reads from collisions, but does not write to it. 17 cdyn2.m Inputs: Outputs: Current time and joint states (t, x), Robot object, Torque function (torqfun), polyhedra, and undetermined extra arguments for the torque function Joint state derivatives for the next time step of ode45 (xd) Algorithm: This function represents the robot dynamic equations for the solver. It takes in the current state, runs the torque function to decide what joint torque to apply and runs accel from the Robot Toolbox to calculate the state derivatives for the next time step. Before ending, however, it restricts the acceleration of certain joints based on information stored in the global variable collisions. These restrictions – in theory – should prevent further intersections from a previously recognized collision event. The restrictions are decided by findRelevantJoints.m and in their current version should work in most cases. Notes: If the functioning of the acceleration restrictions is not acceptable, feel free to alter the way these restrictions are decided in findRelevantJoints.m. See the guide entry for that function for more details. This function reads from collisions, but does not write to it. taufun.m Inputs: Outputs: Current time (t), Current joint positions and velocities (q, qd), Robot object Joint torques (tau) Algorithm: This is a sample function used to set torques as a function of time and the current state of a robot. Any code written to control a robot belongs here. This sample simply sets all joint torques to zero, resulting in a collapse of the arm if run in a simulation. Notes: User-written. intersection.m Inputs: Current time and joint states (t, x), Robot object, Torque function (torqfun), polyhedra, and other undetermined inputs intended for the torque function Outputs: Event function value (value), Boolean command on whether to terminate the solver for a given event (isterminal), and the direction the Event function crossed zero (direction) Algorithms: This function, as the event function for ode45, is run at each solver step. If the event function crosses zero, an event is said to have occurred. See Matlab documentation for more details. collisionCheck is run after initialization, followed by findRelevantJoints. These two functions together completely define the global variable collisions. If any polyhedra are intersecting, the sign of the event function value is changed from negative to positive and isterminal is set to one, halting execution of the solver. 18 Notes: This function writes to collisions. collisionCheck.m Inputs: Robot object, Current joint positions (q), polyhedra, [current time, collisions] Outputs: Boolean value reading true if any polyhedra intersect, [or an updated copy of the global variable collisions] Algorithm: This is essentially two functions combined. The first function simply checks for any polyhedron intersections. The second is meant to be run from intersection.m. This second version is run if it is given the arguments in brackets above, and outputs the global data structure collisions instead of just a Boolean value. Both versions of code run forward kinematics on the polyhedra, use the bounding volume hierarchy to filter out most primitive tests, and then run those primitive tests. The more basic version will terminate as soon as a pair of polyhedron primitives are found to be intersecting. The advanced version called by intersection.m has more steps. Initialization includes reading the optional variables from varargin and slightly different initial sizes for the primitive check matricies, as well as setting a proximity tolerance for deactivating collision states. The bounding hierarchy is the same, but at the primitive tests the algorithm diverges significantly. Old collisions states are automatically tested again for a new proximity value if nothing else. Tests are sorted by whether the collision has or has not already been detected and whether the polyhedra involved are colliding or not. In each case, the collisions data structure is altered in different ways. The advanced version of collisionCheck ends by deleting any collisions that have left become inactive by leaving the proximity tolerance (the polyhedra are no longer close to each other). Notes: In the primitive test case of an old collision that has intersected again, the simulation is probably broken. findRelevantJoints should be setting joint constraints so to prevent this. The current version of the code does nothing special here, but the algorithm could be made to self-diagnose faults by altering collisions in a new way when it encounters this case. Although this code is very long, most of the runtime is spent on gjksubmex. The rest of the function is well vectorized. The user should feel free to alter the value set to proximityTolerance during initialization if it results in unsatisfactory behavior. 19 ptfkin.m Input: Output: Robot object, Current joint positions, polyhedra Polyhedron vertices in current position (transformedPoints), Bounding box vertices in current position (transformedBoundingBoxes), Frame origins in current position (frameOrigins) Algorithm: The algorithm initializes by retrieving the manipulator’s DH parameters from the robot object and creating the index vectors for bb. The function then iterates through each frame of reference in reverse, transforming all points from polypts and bb into the base frame to match the current position of the arm. Notes: This function may be a slight bottleneck in the collision functions. But the algorithm, though computationally intensive, is well vectorized. The benefits of translating this function to a MEX file are unclear. There may be a bug of some sort that causes all objects to be rotated 180 degrees around the local z axis. gjksubmex.m Input: Output: Vertices of two convex polyhedra (A, B) Collision status (c), Indices of points in A and B used in final simplex Q (I), Barycentric coordinates in terms of Q for the final point (Bary) Algorithm: This function applies the Gilbert-Johnson-Keerthi (GJK) algorithm [5] to a pair of convex polyhedra. For details of the main algorithm, see that reference. PtMinNorm.mexw32 is used to find the point on Q closest to the origin, and IndexandSupport.mexw32 is used to remove old points from Q and find a new supporting vertex. Notes: This implementation of GJK is basically a MATLAB skeleton for the MEX files it calls. Since most of the heavy lifting is done in C, this MATLAB code will run relatively quickly. It is used as the basic primitive test for the intersection of the polyhedra composing the model and any bounding volumes. PtMinNorm.mexw32 Input: Vertices of the current simplex (Q) Output: Cartesian (Cart) and barycentric (Bary) coordinates of the point of minimum norm Algorithm: This code finds the closest point on a simplex to the origin by determining the order of the simplex and running the appropriate subroutine. Notes: This function is designed for use in gjksubmex.m, but it may be useful elsewhere. IndexandSupport.mexw32 Input: Vertices of the current simplex (Q), Vertices of the two convex polyhedra (A, B), the Cartesian (Cart) and barycentric (Bary) coordinates of the point of minimum norm 20 Output: Vertices of the new simplex (Q), The new supporting vertex (V), Indices into A and B of the points whose difference resulted in the new supporting vertex (i, j) Algorithm: This function removes unnecessary points from the simplex Q. A point is unnecessary if the barycentric coordinate for that point is zero. It then calculates the next supporting vertex by sampling the Minkowski difference of the two tested polyhedra. It does not calculate the Minkowski sum outright. Notes: This function is also designed for use in gjksubmex.m. Unlike PtMinNorm.mexw32, there is probably no other use for it. findRelevantJoints.m Input: Current joint velocities (qd), collisions, polyhedra Output: collisions Algorithm: This function determines which joints actively affect a collision and decides how to constrain them. This version considers only planar joints and ignores the effects of the waist and camera pan. For each active collision, all the planar degrees of freedom between the two colliding bodies are restricted. There are several exceptions written explicitly into the code where under certain conditions a link may be discounted or an extra one considered. When a new collision is detected, the direction of constraint is determined by the joint velocity at the time of the event. Old collision states keep their directions. A constraint set here causes cdyn2 to disallow any joint acceleration in that direction as long as the collision is active. Notes: This function writes to collisions. While this simple algorithm will prevent intersection in most cases, certain special cases will break it. A case is considered to be broken if an active collision intersects after its collision event. By coordinating this function with collisionCheck it is possible for the simulation to self-diagnose these faults and adjust its behavior. wireAnimate.m Input: Robot object, Time vector (t), Joint position matrix with each row corresponding to a time step (q), polyhedra, Mode keyword (mode) Output: none Algorithm: This algorithm preprocesses an animation of the polyhedra representing a robot, then runs it. In the normal mode, every time step will be used. In the even mode, the largest step size will determine the step size of the animation, and in the discrete mode the animation step size is always set to 0.01. Preprocessing involves trimming the time vector and running forward kinematics on polyhedra for all time steps. To run the animation, 21 wireAnimate calls wireplot at each time step and waits as long as the new time vector dictates. Notes: wireplot.m Input: Output: The animations run very slow compared to real time because wireplot is not fast enough, but in the even or discrete modes all time steps are at least even. Vertices of polyhedra (v), Vector with indices indicating the beginning of each polyhedron in v (e) A solid wireframe plot of all polyhedra in v (Figure 1) Algorithm: The function iterates through each polyhedron. If four or more vertices are given, the vertices are tessellated and plotted with the tetramesh function. If three or fewer vertices are given, lines are plotted connecting each vertex with the others. The colors of the polyhedrons rotate through a colormap. The axes for the figure are manually scaled to the Packbot. Notes: This function runs relatively slowly, but gives a high-quality visualization of the Packbot model (or any other set of polyhedrons). The plot function included in the MATLAB Robotics Toolbox [2] is a better choice for animations. Rmatrix.m Input: Output: Three angles (a1, a2, a3), A string argument identifying the rotation system (system = ‘e’ for Euler angles or ‘rpy’ for roll-pitch-yaw) Rotation matrix (R) Algorithm: This subroutine computes each element of the 3x3 rotation matrix described by the inputs. Notes: none 10.4 Known Issues The primitive test function gjksubmex.m is still a bottleneck in the collision simulations, taking up approximately half of the computation time. This problem does not have to be permanent because although most of the computation involved in the GJK algorithm is done in MEX files, the recursive while loop is still coded in Matlab. If the entire function was converted to C MEX it would cease to be a bottleneck. That said, the simulation as it stands runs in a reasonable time unless the error tolerances are extremely small. This bottleneck should not be a major problem. 22