title: M100, RPi2, Onboard-SDK Camera Sample Failed
body: <p>Camera rotations for v3.2 stopped working on my drone for some reason, so I decided to update to the latest firmware. 
  Running the Onboard-SDK v3.3 on a RPi2 as the onboard computer for a Matrice 100. Running the camera sample failed, the gimbal speed part moved the camera but moving via absolute camera control did not move the camera at all. Camera sample was slightly modified so that the Gimbal speed part was moved further up and an additional rotation was added. Drone and flight controller are updated to the most recent version. Anyone have any advice?</p>
  
  <p>Associated output</p>
  
  <pre><code>ubuntu@ubuntu:~/Drone/Onboard-SDK/build/bin$ ./djiosdk-cameragimbal-
  
  sample UserConfig.txt
  Read App ID
  User Configuration read successfully. 
  
  
  STATUS/1 @ init, L37: Attempting to open device /dev/ttyUSB0 with baudrate 230400...
  
  STATUS/1 @ init, L47: ...Serial started successfully.
  
  STATUS/1 @ parseDroneVersionInfo, L569: Device Serial No. = ---------
  
  STATUS/1 @ parseDroneVersionInfo, L571: Hardware = M100
  
  STATUS/1 @ parseDroneVersionInfo, L572: Firmware = 3.1.10.0
  
  STATUS/1 @ parseDroneVersionInfo, L575: Version CRC = 0xA6453AAC
  
  STATUS/1 @ functionalSetUp, L125: Subscriber not supported!
  
  STATUS/1 @ functionalSetUp, L163: MFIO not supported!
  
  ERROR/1 @ functionalSetUp, L181: Hardware Sync not supported!
  
  STATUS/1 @ activate, L969: version 0x3010A00
  
  STATUS/1 @ activate, L982: Activation successful
  | Available commands:                                            |
  | [a] Exercise gimbal and camera control                         |
  a
  Please note that the gimbal yaw angle you see in the telemetry is w.r.t absolute North, and the accuracy depends on your magnetometer calibration.
  
  Initial Gimbal rotation angle: [0, 0, -27.4]
  
  Setting new Gimbal rotation angle to [0,20,180] using incremental control:
  New Gimbal rotation angle is [0 0 -27.4]
  
  Gimbal Speed Description: 
  
  Roll - unit 0.1 degrees/second input rate [-1800, 1800]
  Pitch - unit 0.1 degrees/second input rate [-1800, 1800]
  Yaw - unit 0.1 degrees/second input rate [-1800, 1800]
  
  Setting Roll rate to 10, Pitch rate to 5, Yaw Rate to -20.
  New Gimbal rotation angle is [15 30 6.8]
  
  Ensure SD card is present.
  Taking picture..
  Check DJI GO App or SD card for a new picture.
  Setting new Gimbal rotation angle to [0,-50, 0] using absolute control:
  New Gimbal rotation angle is [15 30 6.8]
  
  Ensure SD card is present.
  Starting video..
  Setting new Gimbal rotation angle to [0,-50, 0] using absolute control:
  New Gimbal rotation angle is [15 29.9 6.8]
  
  Resetting position...
  New Gimbal rotation angle is [15 29.9 6.8]
  
  Stopping video...
  Check DJI GO App or SD card for a new video
  </code></pre>
  
  <p>Here is the sample code I was trying to run</p>
  
  <pre><code>/*! @file camera_gimbal_sample.cpp
   *  @version 3.3
   *  @date Jun 05 2017
   *
   *  @brief
   *  Camera and Gimbal Control API usage in a Linux environment.
   *  Shows example usage of camera commands and gimbal position/speed control
   *  APIs
   *
   *  @copyright
   *  2017 DJI. All rights reserved.
   * */
  
  #include "camera_gimbal_sample.hpp"
  
  using namespace DJI::OSDK;
  using namespace DJI::OSDK::Telemetry;
  
  int
  main(int argc, char** argv)
  {
  
    // Setup the OSDK: Read config file, create vehicle, activate.
    Vehicle* vehicle = setupOSDK(argc, argv);
    if (vehicle == NULL)
    {
      std::cout &lt;&lt; "Vehicle not initialized, exiting.\n";
      return -1;
    }
  
    // Display interactive prompt
    std::cout
      &lt;&lt; "| Available commands:                                            |"
      &lt;&lt; std::endl;
    std::cout
      &lt;&lt; "| [a] Exercise gimbal and camera control                         |"
      &lt;&lt; std::endl;
    char inputChar;
    std::cin &gt;&gt; inputChar;
  
    switch (inputChar)
    {
      case 'a':
        gimbalCameraControl(vehicle);
        break;
      default:
        break;
    }
  
    delete (vehicle);
    return 0;
  }
  
  bool
  gimbalCameraControl(Vehicle* vehicle)
  {
  
    int responseTimeout = 0;
  
    GimbalContainer              gimbal;
    RotationAngle                initialAngle;
    RotationAngle                currentAngle;
    DJI::OSDK::Gimbal::SpeedData gimbalSpeed;
    int                          pkgIndex;
  
    /*
     * Subscribe to gimbal data not supported in MAtrice 100
     */
  
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      // Telemetry: Verify the subscription
      ACK::ErrorCode subscribeStatus;
      subscribeStatus = vehicle-&gt;subscribe-&gt;verify(responseTimeout);
      if (ACK::getError(subscribeStatus) != ACK::SUCCESS)
      {
        ACK::getErrorCodeMessage(subscribeStatus, __func__);
        return false;
      }
  
      // Telemetry: Subscribe to gimbal status and gimbal angle at freq 10 Hz
      pkgIndex                  = 0;
      int       freq            = 10;
      TopicName topicList10Hz[] = { TOPIC_GIMBAL_ANGLES, TOPIC_GIMBAL_STATUS };
      int       numTopic = sizeof(topicList10Hz) / sizeof(topicList10Hz[0]);
      bool      enableTimestamp = false;
  
      bool pkgStatus = vehicle-&gt;subscribe-&gt;initPackageFromTopicList(
        pkgIndex, numTopic, topicList10Hz, enableTimestamp, freq);
      if (!(pkgStatus))
      {
        return pkgStatus;
      }
      subscribeStatus =
        vehicle-&gt;subscribe-&gt;startPackage(pkgIndex, responseTimeout);
      if (ACK::getError(subscribeStatus) != ACK::SUCCESS)
      {
        ACK::getErrorCodeMessage(subscribeStatus, __func__);
        // Cleanup before return
        vehicle-&gt;subscribe-&gt;removePackage(pkgIndex, responseTimeout);
        return false;
      }
    }
  
    sleep(1);
  
    std::cout
      &lt;&lt; "Please note that the gimbal yaw angle you see in the telemetry is "
         "w.r.t absolute North"
         ", and the accuracy depends on your magnetometer calibration.\n\n";
  
    // Get Gimbal initial values
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      initialAngle.roll  = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().y;
      initialAngle.pitch = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().x;
      initialAngle.yaw   = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().z;
    }
    else
    {
      initialAngle.roll  = vehicle-&gt;broadcast-&gt;getGimbal().roll;
      initialAngle.pitch = vehicle-&gt;broadcast-&gt;getGimbal().pitch;
      initialAngle.yaw   = vehicle-&gt;broadcast-&gt;getGimbal().yaw;
    }
  
    std::cout &lt;&lt; "Initial Gimbal rotation angle: [" &lt;&lt; initialAngle.roll &lt;&lt; ", "
              &lt;&lt; initialAngle.pitch &lt;&lt; ", " &lt;&lt; initialAngle.yaw &lt;&lt; "]\n\n";
  
    // Re-set Gimbal to initial values
    gimbal = GimbalContainer(0, 0, 0, 20, 1, initialAngle);
    doSetGimbalAngle(vehicle, &amp;gimbal);
  
    std::cout &lt;&lt; "Setting new Gimbal rotation angle to [0,20,180] using "
                 "incremental control:\n";
  
    // Get current gimbal data to calc precision error in post processing
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      currentAngle.roll  = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().y;
      currentAngle.pitch = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().x;
      currentAngle.yaw   = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().z;
    }
    else
    {
      currentAngle.roll  = vehicle-&gt;broadcast-&gt;getGimbal().roll;
      currentAngle.pitch = vehicle-&gt;broadcast-&gt;getGimbal().pitch;
      currentAngle.yaw   = vehicle-&gt;broadcast-&gt;getGimbal().yaw;
    }
  
    gimbal = GimbalContainer(0, 200, 1800, 20, 0, initialAngle, currentAngle);
    doSetGimbalAngle(vehicle, &amp;gimbal);
  
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      currentAngle.roll  = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().y;
      currentAngle.pitch = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().x;
      currentAngle.yaw   = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().z;
    }
    else
    {
      currentAngle.roll  = vehicle-&gt;broadcast-&gt;getGimbal().roll;
      currentAngle.pitch = vehicle-&gt;broadcast-&gt;getGimbal().pitch;
      currentAngle.yaw   = vehicle-&gt;broadcast-&gt;getGimbal().yaw;
    }
  
    displayResult(&amp;currentAngle);
  
    // Speed control
  
    std::cout &lt;&lt; "Gimbal Speed Description: \n\n"
              &lt;&lt; "Roll - unit 0.1 degrees/second input rate [-1800, 1800]\n"
              &lt;&lt; "Pitch - unit 0.1 degrees/second input rate [-1800, 1800]\n"
              &lt;&lt; "Yaw - unit 0.1 degrees/second input rate [-1800, 1800]\n\n";
  
    std::cout &lt;&lt; "Setting Roll rate to 10, Pitch rate to 5, Yaw Rate to -20.\n";
    gimbalSpeed.roll  = 1000;
    gimbalSpeed.pitch = 1000;
    gimbalSpeed.yaw   = -1500;
  
    int speedControlDurationMs = 4000;
    int incrementMs            = 100;
    for (int timer = 0; timer &lt; speedControlDurationMs; timer += incrementMs)
    {
      vehicle-&gt;gimbal-&gt;setSpeed(&amp;gimbalSpeed);
      usleep(incrementMs * 1000);
    }
  
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      std::cout &lt;&lt; "M100\n";
      currentAngle.roll  = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().y;
      currentAngle.pitch = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().x;
      currentAngle.yaw   = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().z;
    }
    else
    {
      currentAngle.roll  = vehicle-&gt;broadcast-&gt;getGimbal().roll;
      currentAngle.pitch = vehicle-&gt;broadcast-&gt;getGimbal().pitch;
      currentAngle.yaw   = vehicle-&gt;broadcast-&gt;getGimbal().yaw;
    }
  
    displayResult(&amp;currentAngle);
  
    // Take picture
    std::cout &lt;&lt; "Ensure SD card is present.\n";
    std::cout &lt;&lt; "Taking picture..\n";
    vehicle-&gt;camera-&gt;shootPhoto();
    std::cout &lt;&lt; "Check DJI GO App or SD card for a new picture.\n";
  
    std::cout &lt;&lt; "Setting new Gimbal rotation angle to [0,-50, 0] using absolute "
                 "control:\n";
    gimbal = GimbalContainer(0, -500, 0, 20, 1, initialAngle);
    doSetGimbalAngle(vehicle, &amp;gimbal);
  
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      currentAngle.roll  = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().y;
      currentAngle.pitch = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().x;
      currentAngle.yaw   = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().z;
    }
    else
    {
      currentAngle.roll  = vehicle-&gt;broadcast-&gt;getGimbal().roll;
      currentAngle.pitch = vehicle-&gt;broadcast-&gt;getGimbal().pitch;
      currentAngle.yaw   = vehicle-&gt;broadcast-&gt;getGimbal().yaw;
    }
  
    displayResult(&amp;currentAngle);
  
    // Start video: We will keep the video doing for the duration of the speed
    // control.
    std::cout &lt;&lt; "Ensure SD card is present.\n";
    std::cout &lt;&lt; "Starting video..\n";
    vehicle-&gt;camera-&gt;videoStart();
  
    std::cout &lt;&lt; "Setting new Gimbal rotation angle to [0,-50, 0] using absolute "
                 "control:\n";
    gimbal = GimbalContainer(0, 500, 0, 20, 1, initialAngle);
    doSetGimbalAngle(vehicle, &amp;gimbal);
  
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      currentAngle.roll  = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().y;
      currentAngle.pitch = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().x;
      currentAngle.yaw   = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().z;
    }
    else
    {
      currentAngle.roll  = vehicle-&gt;broadcast-&gt;getGimbal().roll;
      currentAngle.pitch = vehicle-&gt;broadcast-&gt;getGimbal().pitch;
      currentAngle.yaw   = vehicle-&gt;broadcast-&gt;getGimbal().yaw;
    }
  
    displayResult(&amp;currentAngle);
  
  
    // Reset the position
    std::cout &lt;&lt; "Resetting position...\n";
    gimbal = GimbalContainer(0, 0, 0, 20, 1, initialAngle);
    doSetGimbalAngle(vehicle, &amp;gimbal);
  
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      currentAngle.roll  = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().y;
      currentAngle.pitch = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().x;
      currentAngle.yaw   = vehicle-&gt;subscribe-&gt;getValue&lt;TOPIC_GIMBAL_ANGLES&gt;().z;
    }
    else
    {
      currentAngle.roll  = vehicle-&gt;broadcast-&gt;getGimbal().roll;
      currentAngle.pitch = vehicle-&gt;broadcast-&gt;getGimbal().pitch;
      currentAngle.yaw   = vehicle-&gt;broadcast-&gt;getGimbal().yaw;
    }
  
    displayResult(&amp;currentAngle);
  
    // Stop the video
    std::cout &lt;&lt; "Stopping video...\n";
    vehicle-&gt;camera-&gt;videoStop();
    std::cout &lt;&lt; "Check DJI GO App or SD card for a new video.\n";
  
    // Cleanup and exit gimbal sample
    if (!vehicle-&gt;isM100() &amp;&amp; !vehicle-&gt;isLegacyM600())
    {
      ACK::ErrorCode ack =
        vehicle-&gt;subscribe-&gt;removePackage(pkgIndex, responseTimeout);
      if (ACK::getError(ack))
      {
        std::cout
          &lt;&lt; "Error unsubscribing; please restart the drone/FC to get back "
             "to a clean state.\n";
      }
    }
  
    return true;
  }
  
  void
  doSetGimbalAngle(Vehicle* vehicle, GimbalContainer* gimbal)
  {
    DJI::OSDK::Gimbal::AngleData gimbalAngle;
    gimbalAngle.roll     = gimbal-&gt;roll;
    gimbalAngle.pitch    = gimbal-&gt;pitch;
    gimbalAngle.yaw      = gimbal-&gt;yaw;
    gimbalAngle.duration = gimbal-&gt;duration;
    gimbalAngle.mode |= 0;
    gimbalAngle.mode |= gimbal-&gt;isAbsolute;
    gimbalAngle.mode |= gimbal-&gt;yaw_cmd_ignore &lt;&lt; 1;
    gimbalAngle.mode |= gimbal-&gt;roll_cmd_ignore &lt;&lt; 2;
    gimbalAngle.mode |= gimbal-&gt;pitch_cmd_ignore &lt;&lt; 3;
  
    vehicle-&gt;gimbal-&gt;setAngle(&amp;gimbalAngle);
    // Give time for gimbal to sync
    sleep(4);
  }
  
  void
  displayResult(RotationAngle* currentAngle)
  {
    std::cout &lt;&lt; "New Gimbal rotation angle is [";
    std::cout &lt;&lt; currentAngle-&gt;roll &lt;&lt; " ";
    std::cout &lt;&lt; currentAngle-&gt;pitch &lt;&lt; " ";
    std::cout &lt;&lt; currentAngle-&gt;yaw;
    std::cout &lt;&lt; "]\n\n";
  }
  </code></pre>