DEV Community

vmodal_ai
vmodal_ai

Posted on Originally published at v-modal.com

Android SDK for Robot Manipulator and Robotic Arm Control

Android SDK for Robot Manipulator and Robotic Arm Control

Robotic manipulators (6-DOF arms, end-effector grippers) require precise multi-axis positional and trajectory control. An Android manipulator SDK must provide APIs for sending joint-space commands, Cartesian space poses ($X, Y, Z, ext{Roll}, ext{Pitch}, ext{Yaw}$), and real-time jog commands while continuously monitoring joint limits and collision boundaries.

In this tutorial, we will build a Kotlin SDK module for multi-DOF arm trajectory planning and end-effector gripper manipulation.


1. Manipulator Control Topology

+-------------------------------------------------------------+
|                     Android Controller App                  |
|        [Joint Control]      [Cartesian Pose Command]        |
+-------------------------------------------------------------+
                               |
                               v
+-------------------------------------------------------------+
|                 Arm Controller SDK Interface                |
|  - Joint Limit Validation   - Emergency Interlock State     |
+-------------------------------------------------------------+
                               |
                               v
+-------------------------------------------------------------+
|                 Hardware Joint Drivers (CAN/EtherCAT)        |
+-------------------------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

2. Defining Kinematic Models and Joint States

package com.vmodal.sdk.arm.model

data class JointPosition(
    val jointId: Int,
    val positionRadians: Double,
    val velocityRadSec: Double = 0.0,
    val minLimitRad: Double,
    val maxLimitRad: Double
) {
    val isValid: Boolean get() = positionRadians in minLimitRad..maxLimitRad
}

data class CartesianPose(
    val xMeters: Double,
    val yMeters: Double,
    val zMeters: Double,
    val rollRad: Double,
    val pitchRad: Double,
    val yawRad: Double
)

enum class GripperState {
    OPEN,
    CLOSED,
    MOVING,
    FAULT
}
Enter fullscreen mode Exit fullscreen mode

3. Implementing Arm Trajectory Controller

package com.vmodal.sdk.arm

import com.vmodal.sdk.arm.model.CartesianPose
import com.vmodal.sdk.arm.model.GripperState
import com.vmodal.sdk.arm.model.JointPosition

class RoboticArmController(private val numJoints: Int = 6) {

    private val currentJoints = mutableListOf<JointPosition>()
    private var isEmergencyStopped = false

    init {
        // Initialize 6-DOF joint defaults with limit constraints (-PI to +PI)
        for (i in 0 until numJoints) {
            currentJoints.add(
                JointPosition(
                    jointId = i,
                    positionRadians = 0.0,
                    minLimitRad = -Math.PI,
                    maxLimitRad = Math.PI
                )
            )
        }
    }

    fun sendJointPositions(targetJoints: List<Double>): Result<Unit> {
        if (isEmergencyStopped) {
            return Result.failure(IllegalStateException("Arm is in EMERGENCY STOP state!"))
        }

        if (targetJoints.size != numJoints) {
            return Result.failure(IllegalArgumentException("Expected $numJoints joint targets."))
        }

        // Validate joint limits
        for (i in targetJoints.indices) {
            val target = targetJoints[i]
            val limit = currentJoints[i]
            if (target < limit.minLimitRad || target > limit.maxLimitRad) {
                return Result.failure(
                    IllegalArgumentException("Joint $i target $target rad exceeds limit [${limit.minLimitRad}, ${limit.maxLimitRad}]")
                )
            }
        }

        // Hardware command transmission
        println("Transmitting joint targets: $targetJoints")
        return Result.success(Unit)
    }

    fun commandGripper(targetState: GripperState): Boolean {
        if (isEmergencyStopped) return false
        println("Gripper Command: $targetState")
        return true
    }

    fun triggerEmergencyStop() {
        isEmergencyStopped = true
        println("CRITICAL: Arm Emergency Stop Triggered! Motion Locked.")
    }

    fun resetSafetyLock() {
        isEmergencyStopped = false
        println("Safety Lock Cleared.")
    }
}
Enter fullscreen mode Exit fullscreen mode

4. End-to-End Manipulator Control Example

import com.vmodal.sdk.arm.RoboticArmController
import com.vmodal.sdk.arm.model.GripperState

fun main() {
    val armController = RoboticArmController(numJoints = 6)

    println("Moving Arm Joint Positions...")
    val validTarget = listOf(0.5, -0.2, 1.2, 0.0, 0.8, -0.4)
    val result = armController.sendJointPositions(validTarget)

    result.onSuccess {
        println("Arm position target dispatched successfully!")
    }.onFailure { err ->
        println("Failed to move arm: ${err.message}")
    }

    println("
Closing End-Effector Gripper...")
    armController.commandGripper(GripperState.CLOSED)

    println("
Triggering Safety E-Stop...")
    armController.triggerEmergencyStop()

    val attemptResult = armController.sendJointPositions(validTarget)
    if (attemptResult.isFailure) {
        println("Rejected post-E-stop motion request successfully: ${attemptResult.exceptionOrNull()?.message}")
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Enforcing joint limit validation, trajectory safety checks, and hard hardware interlocks inside your Android Manipulator SDK ensures reliable, real-time control over multi-axis robotic arms.


Useful Links

Top comments (0)