Skip to main content

SDK Development Example

This guide explains how to develop and run a C++ application with the RFrame SDK to receive camera images, subscribe to joint states, send a motion command, and check execution results. A single head-pitch movement demonstrates the complete interface invocation workflow.

Workflow: Prepare → Upload → Connect through RobbyantGo → Build and test → Preview → Execute → Inspect results and images.

1. Prerequisites​

  • R2 provides an SSH-accessible development environment with the RFrame SDK, message packages, and build tools installed.
  • The development computer has RobbyantGo installed, can reach the robot, and has login credentials. File transfer examples use the macOS terminal.
  • The robot configuration matches the example. Verify the device state and physical environment before motion. See “Execute head motion” and “Supported environment and limitations”.

The accompanying project directory is rframe_cpp_quickstart.

Upload and download files from the development computer's terminal. Run environment setup, build, and execution commands in RobbyantGo's SSH terminal.

Step 1: Prepare the example project​

Obtain the project and retain this directory structure:

rframe_cpp_quickstart/
├── CMakeLists.txt # Build the program and two data-only tests
├── src/
│ ├── main.cpp # Capture an image, then run the motion workflow
│ └── camera_capture.cpp # Receive and save a compressed image through the SDK
├── include/quickstart/
│ ├── sdk_client.hpp # SDK lifecycle and Service calls
│ ├── joint_feedback.hpp # Subscribe to joint feedback through the SDK
│ ├── motion_profile.hpp # Robot configuration, target calculation, and validation
│ ├── camera_capture.hpp # Camera capture function declaration
│ └── image_file.hpp # Detect image formats from file headers
├── config/
│ ├── channels.json # Joint feedback and motion Service configuration
│ └── camera.json # Head color camera subscription configuration
└── tests/
├── motion_profile_test.cpp # Validate motion targets and data without controlling the robot
└── image_file_test.cpp # Validate format detection and invalid input handling

The C++ source, JSON configuration, and CMake files are ready to run as described, without modification. Motion amplitude and speed scaling are command-line arguments.

The project includes two SDK communication configurations: channels.json for joint feedback and motion interfaces, and camera.json for the camera interface. Keep both files at runtime. The SDK also supports configuration constructed in C++; this guide uses JSON loading.

Step 2: Upload the project​

Upload the entire project to /tmp in the development environment.

In your local terminal, enter the absolute path of the parent directory containing the extracted rframe_cpp_quickstart:

printf 'Absolute path to the example project parent directory: '
read -r SAMPLE_PARENT
cd "${SAMPLE_PARENT}"

Then enter the robot IP address or hostname when prompted:

printf 'Robot IP address or hostname: '
read -r ROBOT_HOST
scp -P 2222 -r ./rframe_cpp_quickstart "robot@${ROBOT_HOST}:/tmp/"

ROBOT_HOST must identify the same robot connected through RobbyantGo.

The uploaded project path is /tmp/rframe_cpp_quickstart.

Step 3: Connect through RobbyantGo​

Connect to the target robot in RobbyantGo and open its SSH function. Authenticate as prompted to enter the robot development environment directly.

Run all subsequent environment setup, build, and execution commands in this terminal.

Step 4: Load the development environment​

Load SDK runtime dependencies and enter the project directory:

source /opt/ros/humble/setup.bash
source /opt/robby/r-types/setup.bash
cd /tmp/rframe_cpp_quickstart

Load the environment for every new RobbyantGo SSH session. The application accesses communication capabilities through the RFrame SDK.

Development directory: You can edit source code directly in the development environment. This example uses /tmp/rframe_cpp_quickstart; edit C++ and JSON files there, then rebuild and rerun. /tmp is intended for temporary validation; keep a copy of important source code on your development computer. If you use /mnt/ssd/workspace as recommended in the development guide, adjust the subsequent source, build, and configuration paths accordingly.

Step 5: Build the program​

Configure the build directory:

cmake -S /tmp/rframe_cpp_quickstart \
-B /tmp/rframe_cpp_quickstart-build \
-DCMAKE_BUILD_TYPE=Release

After configuration succeeds, build:

cmake --build /tmp/rframe_cpp_quickstart-build -j2

Expected result: Built target head_movej_rframe appears. The executable is:

/tmp/rframe_cpp_quickstart-build/head_movej_rframe

Step 6: Run validation tests​

Check target calculation, joint arrays, limits, image format detection, and invalid input handling. These tests do not connect to or move the robot.

ctest --test-dir /tmp/rframe_cpp_quickstart-build --output-on-failure

Expected result: Both motion_profile and image_file pass, with 100% tests passed. The image test checks file-header detection; it does not replace decoding and viewing a real image.

Step 7: Receive an image and preview the motion target​

First receive one head color camera frame through the SDK and save it in the development environment. Then receive real joint feedback, query system state, and calculate the motion target. This step writes an image file but does not send a motion request.

cd /tmp/rframe_cpp_quickstart

/tmp/rframe_cpp_quickstart-build/head_movej_rframe \
--config /tmp/rframe_cpp_quickstart/config/channels.json \
--camera-config /tmp/rframe_cpp_quickstart/config/camera.json \
--output-dir /tmp/rframe-camera \
--delta-deg 3 --scale 0.01

The command uses the two bundled JSON files without changes.

ArgumentPurpose
--configJoint feedback and motion interface configuration
--camera-configCamera interface configuration
--output-dirImage directory, created by the program; on the robot development environment in this example
--delta-deg 3Plan a 3° increase from the current head position
--scale 0.01MoveJ speed scaling, not degrees per second

Expected result:

CAMERA_RECEIVED, CAMERA_SAVED, and CAMERA_OUTPUT appear, with the absolute image path. Capture or save failure exits the program before the motion workflow.

  1. SYSTEM_STATE shows mode=0 state=2 IDLE error=0.
  2. FEEDBACK_READY indicates fresh feedback, a matching joint configuration, and a successful stationary-state check.
  3. Only J_NeckPitch changes by approximately 0.052360 rad (3°) in the target table. The other 19 axis targets remain unchanged.
  4. PREVIEW_COMPLETE and no movement request sent appear.

No MoveJ request is sent without --execute. Resolve missing feedback, incorrect state, configuration mismatches, or failed limit checks before proceeding to motion.

Step 8: Execute head motion​

After preview passes, invoke MoveJ through the SDK to execute one head-pitch movement.

Before execution, verify the robot configuration and limits, ensure nobody is touching the robot, clear its movement range, ensure no other program is controlling motion, and keep the physical emergency stop within reach.

/tmp/rframe_cpp_quickstart-build/head_movej_rframe \
--config /tmp/rframe_cpp_quickstart/config/channels.json \
--camera-config /tmp/rframe_cpp_quickstart/config/camera.json \
--output-dir /tmp/rframe-camera \
--delta-deg 3 --scale 0.01 --execute --profile-reviewed

This execution also saves a new image before previewing motion. No separate camera program is needed.

Execution arguments:

  • --execute: enables the motion confirmation workflow.
  • --profile-reviewed: indicates that the operator has checked the configuration and limits. It does not replace on-site verification.

The program displays the preview again and waits for input. Only entering MOVE continues with state and position checks and sends one motion request. Any other input cancels.

After motion, the robot stays at the target position; it does not automatically return. Each execution adds 3° to the latest position, so repeated executions accumulate displacement.

MoveJ specifies targets for all robot joints. This example changes only the head target; other targets use their positions immediately before sending. If another part moves unexpectedly, use the physical emergency stop directly. Do not rely on the terminal or network to stop the robot.

Step 9: Check execution results​

Check the service response, task status, and joint feedback together. An accepted request means only that the server received it; it does not establish motion completion.

LogMeaningDoes it establish completion?
REQUEST_SENTMoveJ invocation beginsNo
REQUEST_ACCEPTEDResponse received; request acceptedNo
HEAD_FEEDBACKContinuous head feedback: current angle, target angle, and displacement from the pre-send position (°)Observes change; insufficient alone
TASK_STATUS status=2Task is executingNo
TASK_STATUS status=0Server reports task successActual feedback must still be checked
RESULT_VERIFIEDFeedback error, other-axis displacement, stationary-state, and system-state checks passThis example's result checks pass
COMPLETEDNormal workflow ends without returning to the initial positionComplete

Joint subscriptions continue updating during motion. HEAD_FEEDBACK reuses the latest snapshot being checked and logs at most once every 500 ms. current_deg is the current angle, target_deg the target, and moved_deg the change from the position before sending. This log comes from joint feedback; TASK_STATUS comes from task queries. Short tasks or longer Service waits may produce fewer intermediate logs. The final criterion remains RESULT_VERIFIED.

RESULT_VERIFIED indicates feedback error within this example's 0.003 rad threshold, together with successful checks for other joint displacement, stationary state, and system state. This is an example validation threshold, not a product accuracy specification.

For short tasks, status=2 may not be observed. Use the successful task state and final feedback verification as the criteria.

AppCore, ChannelManager, and ROS2 runtime shutdown logs during program exit indicate resource cleanup.

Step 10: Download and view images​

Download images from /tmp/rframe-camera in the development environment to your computer's desktop.

At exit, WORKFLOW_EXIT result=0 image=... reports the result and image path. Execution mode should also show COMPLETED; preview-only mode shows PREVIEW_COMPLETE.

printf 'Robot IP address or hostname: '
read -r ROBOT_HOST
scp -P 2222 -r "robot@${ROBOT_HOST}:/tmp/rframe-camera" "$HOME/Desktop/"
open "$HOME/Desktop/rframe-camera"

Preview and execution each save one frame, so several head_color_... images may exist. Find the filename reported in the current run's logs.

Open that file in the desktop rframe-camera directory.

The output is a single frame captured before motion. The program saves received compressed image data directly and detects .jpg, .png, or .tiff from the file header. OpenCV is not required.

There is no need to rerun the example to download existing images.

2. Interfaces and validation methods​

Validation targetInterface or capabilityMethod
Development environmentCMake, C++ compiler, RFrame, and message packagesUpload the project, load the environment, build, and run
SDK initialization and configurationAppCore, JSON configuration, Channel creationRead bundled JSON, open channels, and complete subsequent communication
Camera receptionTopic: /robby/sensors/camera/head/color/compressedSubscribe to one compressed frame through the SDK, save it, export it, and view it on the computer
Joint receptionTopic: /robotic/joint_statesContinuously receive actual joint positions and velocities to calculate targets, check state, and verify motion
Robot state queryService: /robotic/get_system_state_cmdQuery before and after motion; confirm IDLE, error=0, and other states
Motion controlService: /robotic/movej_cmdBuild targets from current feedback, change only the head-pitch target, and send once after confirmation
Motion task queryService: /robotic/task_status_cmdQuery execution by task ID and confirm success
Actual result verificationTask result + joint feedback + system stateVerify the head reaches its target, other axes remain within program thresholds, and the system returns to idle

The example receives camera and joint data through Topic subscriptions and sends motion commands through Service requests. It does not cover Topic publishing, RPC server development, or independent validation of each communication backend. /robotic/stop_cmd is used for exception handling and is not part of normal execution validation in this workflow.

3. Supported environment and limitations​

This guide assumes R2 already provides an SSH-accessible development environment with the SDK and dependencies installed. If unavailable, prepare it through the applicable delivery process first.

The example applies only to the verified 20-body-axis configuration, with J_NeckPitch as the head joint. Configuration ordering and limits are centralized in motion_profile.hpp; verify them again when changing robots.

The program checks feedback freshness, stationary state, pose drift, and target error, but it is not safety-certified. Synchronous RPC has a 3-second wait budget, and result observation has a 15-second budget. A timeout does not mean server-side motion was canceled. Software stopping can fail during errors and does not replace an on-site physical emergency stop.