Many industrial tilting/sweeping mounts for ROS platforms are out of the budget for your average hobbyist or weekend project enthusiast (Hokuyo UTM-30LX Laser Scanner: ~$6,500.00 USD) so this project aims to create one that fits the budget of your average Joe or broke student. All you need is access to a 3D printer, Amazon, and a local electronic shop like Sayal.

Overview of Camera Mount:

The camera mount runs on a dedicated Arduino Nano sweeping through a range of 130° which auto-zeros upon start up using a limit switch so that the stepper motor never binds from a mechanical restriction. Transforms of the camera are published directly to the /tf topic and are fully compatible with RTABMAP and RVIZ libraries. The assembly uses an Intel Realsense R200 RGBD camera to collect the data.

Tools Required:

  • Soldering Iron
  • Heat Gun
  • Wire Cutters/Strippers
  • Hot Glue Gun

Material Needed:

Step 1: Printing the Frame

The case is available HERE on Thingiverse.com and includes the .STL files to be printed along with the SolidWorks (.sldprt) files for those that would like to modify the CAD files. Follow the printing details in the description for the best quality of print the first time, since printing large flat cases is not very easy due to warping. If you do not have access to a 3D printer then there are several options. First, try Google. Google is great. Second, how about sending your files into an online 3D printing company and have them ship right to your door? Here are some options:

And the list goes on...

Step 2: Assembling the Components

Assemble the Camera Housing

  1. Attach the 10 pin cable to the R200 camera.
  2. Insert the R200 camera into the housing slot.
  3. Attach the housing end cap with the camera cable protruding.

Assemble the Frame

  1. Attach the two side supports to the base using the six screws.
  2. Attach the stepper motor to the upright support.
  3. Insert the ball bearing into the opposite support.
  4. Insert the camera housing into the frame (stepper side first).
  5. Insert screw through the ball bearing to support the camera housing.

Attach the Limit Switch

  1. Solder a servo cable to the three prongs.
  2. Heat shrink the three prongs to avoid short circuiting.
  3. Cut and bend a paper clip into a 'U' bend the same diameter as the holes.
  4. Insert the clip from the outside and feed through the holes on the switch.
  5. Check the switch position by rotating the camera housing.
  6. Bend the paper clip arms to secure.

Step 3: Understanding the Circuit

Before we build any circuits or program the Arduino, let's understand the components that we will be using in this circuit. This may help with troubleshooting further down the line.

ULN2003A Stepper Driver

This is a high voltage, high current Darlington array containing seven open collector common emitter pairs capable of 500mA. There are seven inputs from a microcontroller and seven outputs to the stepper motor with a common pin for power and ground. The datasheet is available HERE.


A capacitor acts to smooth the power supply in a circuit by storing electrical potential energy in the form of a charge that can provide an additional 'boost' to the circuit in times of high current draw from motors starting up. This is helpful to prevent brownout situations that may reset or cause a fault in the microcontroller. Usually, capacitors are denoted by two parallel lines with a gap between them.

Arduino Nano

This is the predecessor of the Arduino Micro but it relatively affordable at only $5 a pop. It utilizes the ATmega328 and can be programmed via a Mini-B USB cable. There is 32KB of Flash Memory and 2KB of SRAM for dynamic variables. See here for all the Specifications.

Limit Switch

A limit switch is a toggle state gate that exclusively connects two of the three pins at a single instance. For our project, the external interrupt pin from the Arduino is attached to the switch to be pulled either high or low.

Step 4: Building & Testing the Circuit

Fortunately, the Kuman Stepper Motor & Driver Kit comes with all the components required to assemble this circuit and they can be salvaged by desoldering them from the board. Remove the capacitor, 5 pin JST socket, and the 16 pin socket from the board.

Note: Remove the ULN2003 IC from the 16 pin socket to prevent heat damage and to make the pins heat up faster.


  • Arduino D8 to ULN2003 1
  • Arduino D7 to ULN2003 2
  • Arduino D6 to ULN2003 3
  • Arduino D5 to ULN2003 4
  • ULN2003 8 to GND
  • ULN2003 9 to VCC

Symbol Nomenclature:

  • VCC - Input Voltage (5-18V)
  • GND - Ground
  • 5V - Regulated 5V output from Arduino board

Step 5: Creating the ROS Package

This tutorial assumes that you already have ROS installed and running on your system. If not, follow these links to get your system up to date:

Navigate to your ROS package directory (usually called your Sandbox) and create a new package for this project.

$ git clone git@github.com:djiglesias/ros-utilities.git
$ cd ros-utilities/

Navigate into the new package and clone the project from GitHub or download it HERE.

$ cd ros_camera_sweep/
$ make

That's it! Now let's upload the code to the Arduino.

Step 6: Programming the Arduino

Launch the Arduino IDE and open main.ino located in your package under src>main. Change the board type to Arduino Nano and select the corresponding port to use. Click the check mark in the top left corner of the Arduino IDE to verify that the code compiles. There will be a warning in the terminal stating that 89% of the dynamic memory is used and that stability problems may occur. This is fine. I thoroughly tested this, and the system is stable as long as there is a minimum of 195 bytes (90%) remaining. Unfortunately, this means that there is no additional room for adding in features such as subscribers or services.

Sketch uses 15256 bytes (49%) of program storage space. Maximum is 30720 bytes. Global variables use 1826 bytes (89%) of dynamic memory, leaving 222 bytes for local variables. Maximum is 2048 bytes. Low memory available, stability problems may occur.


  • Modified tf/tf.h library with additional functions for converting Euler angles to quaternions.
  • Modified Stepper.h library that reorders the sequence of firing pins on the stepper.
  • Uses an additional class, CameraPan, to wrap the Stepper class.
  • Adapted from the TimeTF example in the ros_lib package (File>Examples>ros_lib>TimeTF).

While uploading the code the Arduino for the first time, comment out the following line in `void setup()` which is responsible for holding up the camera mount from moving until it has connected with the ROS master.

$ while( ! nh.connected() ) { nh.spinOnce(); }

Step 7: Assembling the Circuit

Layout the Components:

  1. IN1 on ULN2003 IC inline with D8 on Arduino.
  2. IN4 on ULN2003 IC inline with D5 on Arduino.
  3. GND on ULN2003 IC inline with GND on Arduino.
  4. Capacitor connects VCC and GND on ULN2003 IC.
  5. Align JST Pin 1-4 with OUT1-4 on ULN2003 IC.

Interrupt Connector:

  1. Place a 3x1 header pin in an open space.
  2. Connect middle pin to 5V.
  3. Connect an outside pin to GND.
  4. Connect the remaining pin to D2.

Final Touches:

  1. Apply hot glue to the back side of the perfboard to insulate the pins.
  2. Cut off ISP header pins for lower profile.

Step 8: Visualizing in RVIZ

Once everything is assembled, let's plug the Arduino into the computer and test it out using RVIZ as the visualizer. If you uncommented the line from Step 6: Programming the Arduino then the assembly should not be doing anything until the Rosserial node has been initialized. Find out what port the Arduino is on (usually /dev/ttyUSB0 or /dev/ttyUSB1) and run the launch file to view the axes. Defaults to "/dev/ttyUSB0" so if on a different port then add port:="/dev/ttyUSB#" as an argument, replacing '#' with the port number.

$ roslaunch ros_camera_sweep view.launch

This should initialize the Arduino and it will jump into its auto-zeroing routine before beginning to publish its transforms to RVIZ. The camera will run continuously until RVIZ has been closed, at which point the camera will complete the motion cycle it is currently on and then come to a stop. Alternatively, you can visualize the camera assembly in its .stl form using the following launch file.

$ roslaunch ros_camera_sweep view.launch model:="true"

Once these are working as intended, let's attached the Intel® RealSense R200 camera and visualize the point cloud in real time.

$ roslaunch ros_camera_sweep view.launch model:="true" camera:="true"

Note: The base frame for the depth camera was set to 'camera_link' to be associated with the transforms being published from the camera sweeping mount.

Step 9: Using Camera With SLAM (RTABMAP)

Using Visual Odometry

Launch rtabmap from the command line using the predefined launch file provided. Unless you want to build upon an existing map, provide the argument for deleting the database on start up. If your Arduino is not on ttyUSB0, then you can provide the port using port:="/dev/ttyUSB#".

$ roslaunch ros_camera_sweep rtabmap.launch rtabmap_args:="-- delete_db_on_start"

Using Custom Odometry
For the cases where an existing odometry topic is already defined, you must disable rtab's visual odometry function and provide the appropriate topic pathway. The default odometry topic is /odom, however may be updated by passing in odom_topic:="new_odom_topic" to the launch file.

$ roslaunch ros_camera_sweep rtabmap.launch rtabmap_args:="-- delete_db_on_start" visual_odometry:="false"

Images coming soon.

About This Instructable



Bio: Avid tinkerer and enjoys weekend projects in almost anything tech related. Mainly interested in UAVs, 3D printing, and software. Always open for new ideas!
More by Duncan Iglesias:Sweeping Camera Mount (ROS) Retro Gaming Console (N64 Mod) With KODI 1S-6S Battery Voltage Monitor (ROS) 
Add instructable to: