cd /news/robotics/android-ros-2-building-a-robot-contr… · home topics robotics article
[ARTICLE · art-100412] src=dev.to ↗ pub= topic=robotics verified=true sentiment=· neutral

Android + ROS 2: Building a Robot Control App with Kotlin

A developer demonstrates how to build an Android robot control app in Kotlin that communicates with a ROS 2 robot, using a bridge or gateway to expose only necessary topics. The app uses Jetpack Compose for the UI, Kotlin coroutines and StateFlow for telemetry, and includes a command watchdog for safety. The tutorial emphasizes testing against a simulator before deploying to physical hardware.

read3 min views2 publishedAug 17, 2026

Physical AI is bringing together robotics, edge computing, computer vision, and intelligent mobile interfaces. Android is a useful companion platform because modern phones and tablets provide touch interfaces, cameras, sensors, networking, and strong edge-computing capabilities.

In this tutorial, we will design an Android application in Kotlin that communicates with a ROS 2 robot. The app will provide a simple control interface for sending movement commands and receiving robot telemetry.

A practical architecture can look like this:

Android App
   |
   | ROS 2 bridge / WebSocket / MQTT
   v
ROS 2 Middleware
   |
   +---- /cmd_vel ----> Robot Base
   |
   +---- /odom -------> Telemetry
   |
   +---- /battery ----> Battery Status

The Android application should not directly control motors. Instead, it communicates with a ROS 2 node or bridge responsible for validating commands and interfacing with the robot.

Create a Kotlin Android project using Android Studio.

A clean package structure is:

com.example.robotcontroller
├── ui
├── ros
├── model
├── network
└── MainActivity.kt

Keep the ROS communication layer separate from the Compose UI so that the application can later switch between a simulator, development robot, or production robot.

Create a simple command model:

data class VelocityCommand(
    val linearX: Double,
    val angularZ: Double
)

The UI can map buttons or a virtual joystick to these values.

For example:

fun moveForward() = VelocityCommand(
    linearX = 0.5,
    angularZ = 0.0
)

fun stop() = VelocityCommand(
    linearX = 0.0,
    angularZ = 0.0
)

The communication layer then converts the command into the message format expected by your ROS 2 bridge.

A simple control panel can be created with Jetpack Compose:

@Composable
fun RobotControls(
    onForward: () -> Unit,
    onBackward: () -> Unit,
    onLeft: () -> Unit,
    onRight: () -> Unit,
    onStop: () -> Unit
) {
    Column {
        Button(onClick = onForward) {
            Text("Forward")
        }

        Row {
            Button(onClick = onLeft) {
                Text("Left")
            }

            Button(onClick = onStop) {
                Text("Stop")
            }

            Button(onClick = onRight) {
                Text("Right")
            }
        }

        Button(onClick = onBackward) {
            Text("Backward")
        }
    }
}

For a real robot, replace these buttons with a joystick or gesture-based controller.

The Android app needs a communication mechanism between the mobile device and ROS 2. A common architecture is to expose selected ROS 2 topics through a bridge or gateway.

The Android client can then publish commands such as:

/cmd_vel

and subscribe to telemetry topics such as:

/odom
/battery_state
/robot_status

Avoid exposing the entire ROS graph directly to an untrusted mobile client. Expose only the topics and services required by the application.

Represent telemetry in Kotlin:

data class RobotTelemetry(
    val battery: Float,
    val x: Double,
    val y: Double,
    val connected: Boolean
)

Use Kotlin coroutines and StateFlow

to expose updates to Compose:

private val _telemetry = MutableStateFlow(
    RobotTelemetry(0f, 0.0, 0.0, false)
)

val telemetry: StateFlow<RobotTelemetry> = _telemetry

Compose can collect this state and update the dashboard automatically.

A robot-control application should include a reliable stop mechanism.

Implement:

A particularly useful technique is a command watchdog: if the robot does not receive a valid command within a defined interval, the control node should command zero velocity.

Before connecting physical hardware, test the Android application against a simulated ROS 2 robot.

A simulator lets you verify:

This dramatically reduces the risk of testing incorrect commands on physical hardware.

For a production system, consider:

Android / Kotlin
       |
   Secure Gateway
       |
      ROS 2
       |
 Navigation / Perception
       |
 Robot Hardware

This separation allows the Android application to remain a user interface while ROS 2 handles robotics workloads.

Android and Kotlin can provide a powerful human interface for Physical AI systems. By combining Jetpack Compose, Kotlin coroutines, secure networking, and ROS 2, you can build mobile applications that monitor and control robots without coupling the Android UI directly to robot hardware.

The same architecture can later be extended with camera streaming, AI perception, voice commands, autonomous navigation, and LLM-based robot control.

SDK Flutter: https://github.com/v-modal/vmodal_sdk_flutter

SDK Android: https://github.com/v-modal/vmodal_sdk_android

Discord: https://discord.gg/K72z28KUx

── more in #robotics 4 stories · sorted by recency
── more on @android 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/android-ros-2-buildi…] indexed:0 read:3min 2026-08-17 ·