Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RSDK-8714: Arm wrappers #66

Merged
merged 4 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import com.viam.common.v1.Common;
import com.viam.common.v1.Common.ResourceName;
import com.viam.component.arm.v1.ArmServiceGrpc;
import com.viam.component.board.v1.BoardServiceGrpc;
import com.viam.component.camera.v1.CameraServiceGrpc;
import com.viam.component.generic.v1.GenericServiceGrpc;
import com.viam.component.gripper.v1.GripperServiceGrpc;
import com.viam.component.motor.v1.MotorServiceGrpc;
import com.viam.component.movementsensor.v1.MovementSensorServiceGrpc;
import com.viam.component.sensor.v1.SensorServiceGrpc;
import com.viam.sdk.core.component.arm.*;
import com.viam.component.servo.v1.ServoServiceGrpc;
import com.viam.sdk.core.component.board.Board;
import com.viam.sdk.core.component.board.BoardRPCClient;
Expand Down Expand Up @@ -99,6 +101,12 @@ public class ResourceManager implements Closeable {
SensorRPCService::new,
SensorRPCClient::new
));
Registry.registerSubtype(new ResourceRegistration<>(
Arm.SUBTYPE,
ArmServiceGrpc.SERVICE_NAME,
ArmRPCService::new,
ArmRPCClient::new
));
Registry.registerSubtype(new ResourceRegistration<>(
Servo.SUBTYPE,
ServoServiceGrpc.SERVICE_NAME,
Expand Down
160 changes: 160 additions & 0 deletions core/sdk/src/main/kotlin/com/viam/sdk/core/component/arm/Arm.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package com.viam.sdk.core.component.arm

import com.google.protobuf.ByteString
import com.google.protobuf.Struct
import com.viam.common.v1.Common.KinematicsFileFormat
import com.viam.common.v1.Common.Pose
import com.viam.common.v1.Common.ResourceName
import com.viam.component.arm.v1.Arm.JointPositions
import com.viam.sdk.core.component.Component
import com.viam.sdk.core.component.arm.Arm
import com.viam.sdk.core.resource.Resource
import com.viam.sdk.core.resource.Subtype
import com.viam.sdk.core.robot.RobotClient

/**
* An Arm represents a physical robot arm that exists in three-dimensional space.
*/
abstract class Arm(name: String) : Component(SUBTYPE, named(name)) {
companion object {
@JvmField
val SUBTYPE = Subtype(Subtype.NAMESPACE_RDK, Subtype.RESOURCE_TYPE_COMPONENT, "arm")

/**
* Get the ResourceName of the component
* @param name the name of the component
* @return the component's ResourceName
*/
@JvmStatic
fun named(name: String): ResourceName {
return Resource.named(SUBTYPE, name)
}

/**
* Get the component with the provided name from the provided robot.
* @param robot the RobotClient
* @param name the name of the component
* @return the component
*/
@JvmStatic
fun fromRobot(robot: RobotClient, name: String): Arm {
return robot.getResource(Arm::class.java, named(name))
}
}

/**
* Get the current position of the end of the arm expressed as a ``Pose``.
* @return A representation of the arm's current position as a 6 DOF (six degrees of freedom) pose.
* The ``Pose`` is composed of values for location and orientation with respect to the origin.
* Location is expressed as distance, which is represented by x, y, and z coordinate values.
* Orientation is expressed as an orientation vector, which is represented by o_x, o_y, o_z, and theta values.
*/
abstract fun getEndPosition(extra: Struct) : Pose

/**
* Get the current position of the end of the arm expressed as a ``Pose``.
* @return A representation of the arm's current position as a 6 DOF (six degrees of freedom) pose.
* The ``Pose`` is composed of values for location and orientation with respect to the origin.
* Location is expressed as distance, which is represented by x, y, and z coordinate values.
* Orientation is expressed as an orientation vector, which is represented by o_x, o_y, o_z, and theta values.
*/
fun getEndPosition() : Pose{
return getEndPosition(Struct.getDefaultInstance())
}

/**
* Move the end of the arm to the Pose specified in ``pose``.
* @param pose The destination ``Pose`` for the arm. The ``Pose`` is composed of values for location and orientation
* with respect to the origin.
* Location is expressed as distance, which is represented by x, y, and z coordinate values.
* Orientation is expressed as an orientation vector, which is represented by o_x, o_y, o_z, and theta values.

*/
abstract fun moveToPosition(pose: Pose, extra: Struct)

/**
* Move the end of the arm to the Pose specified in ``pose``.
* @param pose The destination ``Pose`` for the arm. The ``Pose`` is composed of values for location and orientation
* with respect to the origin.
* Location is expressed as distance, which is represented by x, y, and z coordinate values.
* Orientation is expressed as an orientation vector, which is represented by o_x, o_y, o_z, and theta values.

*/
fun moveToPosition(pose: Pose) {
moveToPosition(pose, Struct.getDefaultInstance())
}

/**
* Move each joint on the arm to the corresponding angle specified in ``positions``.
* @param positions the destination ``JointPositions`` for the arm
*/
abstract fun moveToJointPositions(positions: JointPositions, extra: Struct)

/**
* Move each joint on the arm to the corresponding angle specified in ``positions``.
* @param positions the destination ``JointPositions`` for the arm
*/
fun moveToJointPositions(positions: JointPositions){
return moveToJointPositions(positions, Struct.getDefaultInstance())
}

/**
* Get the JointPositions representing the current position of the arm.
* @return The current ``JointPositions`` for the arm.
* ``JointPositions`` can have one attribute, ``values``, a list of joint positions with rotational values (degrees)
* and translational values (mm).
*/
abstract fun getJointPositions(extra: Struct) : JointPositions

/**
* Get the JointPositions representing the current position of the arm.
* @return The current ``JointPositions`` for the arm.
* ``JointPositions`` can have one attribute, ``values``, a list of joint positions with rotational values (degrees)
* and translational values (mm).
*/
fun getJointPositions() : JointPositions{
return getJointPositions(Struct.getDefaultInstance())
}


/**
* Stop all motion of the arm. It is assumed that the arm stops immediately.
*/
abstract fun stop(extra: Struct)

/**
* Stop all motion of the arm. It is assumed that the arm stops immediately.
*/
fun stop(){
stop(Struct.getDefaultInstance())
}

/**
* Get if the arm is currently moving.
* @return whether the arm is moving
*/
abstract fun isMoving(): Boolean


/**
* Get the kinematics information associated with the arm.
* @return A pair containing two values; the first [0] value represents the format of the
* file, either in URDF format (``KinematicsFileFormat.KINEMATICS_FILE_FORMAT_URDF``) or
* Viam's kinematic parameter format (spatial vector algebra) (``KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA``),
* and the second [1] value represents the byte contents of the file.
*/
abstract fun getKinematics(extra: Struct): Pair<KinematicsFileFormat, ByteString>

/**
* Get the kinematics information associated with the arm.
* @return A pair containing two values; the first [0] value represents the format of the
* file, either in URDF format (``KinematicsFileFormat.KINEMATICS_FILE_FORMAT_URDF``) or
* Viam's kinematic parameter format (spatial vector algebra) (``KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA``),
* and the second [1] value represents the byte contents of the file.
*/
fun getKinematics(): Pair<KinematicsFileFormat, ByteString>{
return getKinematics(Struct.getDefaultInstance())
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.viam.sdk.core.component.arm

import com.google.protobuf.ByteString
import com.google.protobuf.Struct
import com.google.protobuf.Value
import com.viam.common.v1.Common
import com.viam.common.v1.Common.GetGeometriesRequest
import com.viam.common.v1.Common.GetKinematicsRequest
import com.viam.component.arm.v1.Arm.*
import com.viam.component.arm.v1.ArmServiceGrpc
import com.viam.component.arm.v1.ArmServiceGrpc.ArmServiceBlockingStub
import com.viam.sdk.core.rpc.Channel
import java.util.*
import kotlin.jvm.optionals.getOrDefault

class ArmRPCClient(name: String, channel: Channel) : Arm(name) {
private val client: ArmServiceBlockingStub

init {
val client = ArmServiceGrpc.newBlockingStub(channel)
if (channel.callCredentials.isPresent) {
this.client = client.withCallCredentials(channel.callCredentials.get())
} else {
this.client = client
}
}

override fun getEndPosition(extra: Struct): Common.Pose {
val request = GetEndPositionRequest.newBuilder().setName(this.name.name).setExtra(extra).build()
val response = this.client.getEndPosition(request)
return response.pose
}

override fun moveToPosition(pose: Common.Pose, extra: Struct) {
val request = MoveToPositionRequest.newBuilder().setName(this.name.name).setTo(pose).setExtra(extra).build()
this.client.moveToPosition(request)

}

override fun moveToJointPositions(positions: JointPositions, extra: Struct) {
val request = MoveToJointPositionsRequest.newBuilder().setName(this.name.name).setPositions(positions).setExtra(extra).build()
this.client.moveToJointPositions(request)
}

override fun getJointPositions(extra: Struct): JointPositions {
val request = GetJointPositionsRequest.newBuilder().setName(this.name.name).setExtra(extra).build()
val response = this.client.getJointPositions(request)
return response.positions
}

override fun stop(extra: Struct) {
val request = StopRequest.newBuilder().setName(this.name.name).setExtra(extra).build()
this.client.stop(request)
}

override fun isMoving(): Boolean {
val request = IsMovingRequest.newBuilder().setName(this.name.name).build()
val response = this.client.isMoving(request)
return response.isMoving
}

override fun getKinematics(extra: Struct): Pair<Common.KinematicsFileFormat, ByteString> {
val request = GetKinematicsRequest.newBuilder().setName(this.name.name).setExtra(extra).build()
val response = this.client.getKinematics(request)
return (response.format to response.kinematicsData)
}

override fun doCommand(command: Map<String, Value>?): Struct {
val request = Common.DoCommandRequest.newBuilder().setName(this.name.name)
.setCommand(Struct.newBuilder().putAllFields(command).build()).build()
val response = this.client.doCommand(request)
return response.result
}

override fun getGeometries(extra: Optional<Struct>): List<Common.Geometry> {
val request = GetGeometriesRequest.newBuilder().setName(this.name.name)
.setExtra(extra.getOrDefault(Struct.getDefaultInstance())).build()
val response = this.client.getGeometries(request)
return response.geometriesList
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.viam.sdk.core.component.arm

import com.viam.common.v1.Common.*
import com.viam.component.arm.v1.ArmServiceGrpc
import com.viam.component.arm.v1.Arm.*
import com.viam.sdk.core.resource.ResourceManager
import com.viam.sdk.core.resource.ResourceRPCService
import io.grpc.stub.StreamObserver
import java.util.*

internal class ArmRPCService(private val manager: ResourceManager) : ArmServiceGrpc.ArmServiceImplBase(), ResourceRPCService<Arm> {
override fun getEndPosition(
request: GetEndPositionRequest,
responseObserver: StreamObserver<GetEndPositionResponse>
) {
val arm = getResource(Arm.named(request.name))
val endPosition = arm.getEndPosition(request.extra)
responseObserver.onNext(GetEndPositionResponse.newBuilder().setPose(endPosition).build())
responseObserver.onCompleted()
}

override fun moveToPosition(
request: MoveToPositionRequest,
responseObserver: StreamObserver<MoveToPositionResponse>
) {
val arm = getResource(Arm.named(request.name))
arm.moveToPosition(request.to, request.extra)
responseObserver.onNext(MoveToPositionResponse.newBuilder().build())
responseObserver.onCompleted()
}

override fun getJointPositions(
request: GetJointPositionsRequest,
responseObserver: StreamObserver<GetJointPositionsResponse>
) {
val arm = getResource(Arm.named(request.name))
val positions = arm.getJointPositions(request.extra)
responseObserver.onNext(GetJointPositionsResponse.newBuilder().setPositions(positions).build())
responseObserver.onCompleted()
}

override fun moveToJointPositions(
request: MoveToJointPositionsRequest,
responseObserver: StreamObserver<MoveToJointPositionsResponse>
) {
val arm = getResource(Arm.named(request.name))
arm.moveToJointPositions(request.positions, request.extra)
responseObserver.onNext(MoveToJointPositionsResponse.newBuilder().build())
responseObserver.onCompleted()
}

override fun getKinematics(
request: GetKinematicsRequest,
responseObserver: StreamObserver<GetKinematicsResponse>
) {
val arm = getResource(Arm.named(request.name))
val kinematics = arm.getKinematics( request.extra)
responseObserver.onNext(GetKinematicsResponse.newBuilder().setFormat(kinematics.first).setKinematicsData(kinematics.second).build())
responseObserver.onCompleted()
}

override fun stop(
request: StopRequest, responseObserver: StreamObserver<StopResponse>
) {
val arm = getResource(Arm.named(request.name))
arm.stop(request.extra)
responseObserver.onNext(StopResponse.newBuilder().build())
responseObserver.onCompleted()
}


override fun isMoving(
request: IsMovingRequest, responseObserver: StreamObserver<IsMovingResponse>
) {
val arm = getResource(Arm.named(request.name))
val isMoving = arm.isMoving()
responseObserver.onNext(
IsMovingResponse.newBuilder().setIsMoving(isMoving).build()
)
responseObserver.onCompleted()
}

override fun doCommand(
request: DoCommandRequest, responseObserver: StreamObserver<DoCommandResponse>
) {
val arm = getResource(Arm.named(request.name))
val result = arm.doCommand(request.command.fieldsMap)
responseObserver.onNext(DoCommandResponse.newBuilder().setResult(result).build())
responseObserver.onCompleted()
}

override fun getGeometries(
request: GetGeometriesRequest, responseObserver: StreamObserver<GetGeometriesResponse>
) {
val arm = getResource(Arm.named(request.name))
val result = arm.getGeometries(Optional.of(request.extra))
responseObserver.onNext(GetGeometriesResponse.newBuilder().addAllGeometries(result).build())
responseObserver.onCompleted()
}

override fun getResourceClass(): Class<Arm> {
return Arm::class.java
}

override fun getManager(): ResourceManager {
return this.manager
}
}
Loading