I am using Aruco tags to locate mobile robots relative to one another. I have mounted tags on the robots using cubes so that at least one tag will be visible from every side of the robot.
In the picture above, the origin is indicated by the red, green, and blue lines overplayed over the video frame.
In the past, I had been locating each of the tags individually, but the Aruco library offers a higher precision alternative: Aruco tag boards. Aruco tag boards consist of multiple Aruco tags. The position of the tags is defined in three dimensions a-priori, so when multiple tags appear in a frame, a better estimate of the tag boards location can be calculated than using just one single Aruco tag alone.
This post presents information on how I:
- learned to define Aruco Boards,
- defined the Aruco Board pictured above,
- obtained Aruco Board Pose estimates.
Learning to Define Aruco Boards
Aruco boards require three parameter: objPoints, dictionary, and ids. To learn how these variables are formatted, I used the GridBoard_create method to generate an example. Following is the contents of those variables for:
board = aruco.GridBoard_create(2,2,5,5, aruco.getPredefinedDictionary(aruco.DICT_6X6_250)) board.objPoints = [array([[ 0., 15., 0.], [ 5., 15., 0.], [ 5., 10., 0.], [ 0., 10., 0.]], dtype=float32), array([[ 10., 15., 0.], [ 15., 15., 0.], [ 15., 10., 0.], [ 10., 10., 0.]], dtype=float32), array([[ 0., 5., 0.], [ 5., 5., 0.], [ 5., 0., 0.], [ 0., 0., 0.]], dtype=float32), array([[ 10., 5., 0.], [ 15., 5., 0.], [ 15., 0., 0.], [ 10., 0., 0.]], dtype=float32)] board.ids = array([, , , ], dtype=int32)
Defining My Cubic Aruco Board
For my 3-D board:
board_corners = [np.array([[0.09,0.01,0.0],[0.09,0.09,0.],[0.01,0.09,0.],[0.01,0.01,0.]],dtype=np.float32), np.array([[0.09,0.10,0.01],[0.09,0.10,0.09],[0.01,0.10,0.09],[0.01,0.10,0.01]],dtype=np.float32), np.array([[0.09,0.0,0.09],[0.09,0.0,0.01],[0.01,0.0,0.01],[0.01,0.0,0.09]],dtype=np.float32), np.array([[0.09,0.09,0.10],[0.09,0.01,0.10],[0.01,0.01,0.10],[0.01,0.09,0.10]],dtype=np.float32)] board_ids = np.array( [,,,], dtype=np.int32) board = aruco.Board_create( board_corners, aruco.getPredefinedDictionary(aruco.DICT_6X6_250), board_ids )
In this case, the model was defined by hand. For more complicated three-dimensional shapes, I will use CAD tools to calculate the tag corners.
Displaying an Aruco Board Pose
After defining the board, I was able to estimate the pose of the board as follow:
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, aruco_dict) retval,rvec,tvec = aruco.estimatePoseBoard( corners, ids, board, camera_matrix, dist_coeffs ) frame = aruco.drawAxis( frame, camera_matrix, dist_coeffs, rvec, tvec, aruco_marker_length_meters ) frame = aruco.drawDetectedMarkers( frame, corners, ids )
As shown in the picture above, the individual markers are outlined and labeled with their respective id numbers. The axis are drawn on from the origin, with x-axis red, y-axis green, and z-axis blue.