Skip to content

Commit

Permalink
RSDK-8714: Encoder wrappers (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
gloriacai01 authored Sep 11, 2024
1 parent 9fe3a05 commit 698114b
Show file tree
Hide file tree
Showing 7 changed files with 558 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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.encoder.v1.EncoderServiceGrpc;
import com.viam.component.gantry.v1.GantryServiceGrpc;
import com.viam.component.generic.v1.GenericServiceGrpc;
import com.viam.component.gripper.v1.GripperServiceGrpc;
Expand All @@ -20,6 +21,7 @@
import com.viam.sdk.core.component.camera.Camera;
import com.viam.sdk.core.component.camera.CameraRPCClient;
import com.viam.sdk.core.component.camera.CameraRPCService;
import com.viam.sdk.core.component.encoder.*;
import com.viam.sdk.core.component.gantry.Gantry;
import com.viam.sdk.core.component.gantry.GantryRPCClient;
import com.viam.sdk.core.component.gantry.GantryRPCService;
Expand Down Expand Up @@ -109,6 +111,12 @@ public class ResourceManager implements Closeable {
SensorRPCService::new,
SensorRPCClient::new
));
Registry.registerSubtype(new ResourceRegistration<>(
Encoder.SUBTYPE,
EncoderServiceGrpc.SERVICE_NAME,
EncoderRPCService::new,
EncoderRPCClient::new
));
Registry.registerSubtype(new ResourceRegistration<>(
PowerSensor.SUBTYPE,
PowerSensorServiceGrpc.SERVICE_NAME,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.viam.sdk.core.component.encoder

import com.google.protobuf.Struct
import com.viam.common.v1.Common.ResourceName
import com.viam.component.encoder.v1.Encoder.GetPropertiesResponse
import com.viam.component.encoder.v1.Encoder.PositionType
import com.viam.sdk.core.component.Component
import com.viam.sdk.core.resource.Resource
import com.viam.sdk.core.resource.Subtype
import com.viam.sdk.core.robot.RobotClient

typealias Properties = GetPropertiesResponse


/**
* An [Encoder] represents a physical encoder.
*/
abstract class Encoder(name: String) : Component(SUBTYPE, named(name)) {

companion object {
@JvmField
val SUBTYPE = Subtype(Subtype.NAMESPACE_RDK, Subtype.RESOURCE_TYPE_COMPONENT, "encoder")

/**
* 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): Encoder {
return robot.getResource(Encoder::class.java, named(name))
}
}

/**
* Set the current position to be the new zero (home) position.
*/
abstract fun resetPosition(extra: Struct)

/**
* Set the current position to be the new zero (home) position.
*/
fun resetPosition() {
resetPosition(Struct.getDefaultInstance())
}

/**
* Report the position of the encoder.
* The value returned is the current position in terms of its ``position_type``.
* If no position type is given, the supported position type will be returned.
* The position will be either in relative units (ticks away from a zero position) for
* ``PositionType.POSITION_TYPE_TICKS_COUNT`` or absolute units (degrees along a circle)
* for ``PositionType.POSITION_TYPE_ANGLE_DEGREES``.
* @param positionType The desired output type of the position.
* @return A tuple containing two values; the first [0] the position of the encoder which can either be
* ticks since last zeroing for a relative encoder or degrees for an absolute encoder, and the second [1] the type of
* position the encoder returns (ticks or degrees).
*
*/
abstract fun getPosition(positionType: PositionType?, extra: Struct): Pair<Float, PositionType>

/**
* Report the position of the encoder.
* The value returned is the current position in terms of its ``position_type``.
* If no position type is given, the supported position type will be returned.
* The position will be either in relative units (ticks away from a zero position) for
* ``PositionType.POSITION_TYPE_TICKS_COUNT`` or absolute units (degrees along a circle)
* for ``PositionType.POSITION_TYPE_ANGLE_DEGREES``.
* @return A tuple containing two values; the first [0] the position of the encoder which can either be
* ticks since last zeroing for a relative encoder or degrees for an absolute encoder, and the second [1] the type of
* position the encoder returns (ticks or degrees).
*/
fun getPosition(positionType: PositionType): Pair<Float, PositionType> {
return getPosition(positionType, Struct.getDefaultInstance())
}

/**
* Report the position of the encoder.
* The value returned is the current position in terms of its ``position_type``.
* If no position type is given, the supported position type will be returned.
* The position will be either in relative units (ticks away from a zero position) for
* ``PositionType.POSITION_TYPE_TICKS_COUNT`` or absolute units (degrees along a circle)
* for ``PositionType.POSITION_TYPE_ANGLE_DEGREES``.
* @return A tuple containing two values; the first [0] the position of the encoder which can either be
* ticks since last zeroing for a relative encoder or degrees for an absolute encoder, and the second [1] the type of
* position the encoder returns (ticks or degrees).
*
*/
fun getPosition(extra: Struct): Pair<Float, PositionType> {
return getPosition(null, extra)
}

/**
* Report the position of the encoder.
* The value returned is the current position in terms of its ``position_type``.
* If no position type is given, the supported position type will be returned.
* The position will be either in relative units (ticks away from a zero position) for
* ``PositionType.POSITION_TYPE_TICKS_COUNT`` or absolute units (degrees along a circle)
* for ``PositionType.POSITION_TYPE_ANGLE_DEGREES``.
* @return A tuple containing two values; the first [0] the position of the encoder which can either be
* ticks since last zeroing for a relative encoder or degrees for an absolute encoder, and the second [1] the type of
* position the encoder returns (ticks or degrees).
*/
fun getPosition(): Pair<Float, PositionType> {
return getPosition(null, Struct.getDefaultInstance())
}


/**
* Return a dictionary of the types of position reporting this encoder supports.
* @return a map of position types to supported status.
*/
abstract fun getProperties(extra: Struct): Properties

/**
* Return a dictionary of the types of position reporting this encoder supports.
* @return a map of position types to supported status.
*/
fun getProperties(): Properties {
return getProperties(Struct.getDefaultInstance())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.viam.sdk.core.component.encoder

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.component.encoder.v1.Encoder.*
import com.viam.component.encoder.v1.EncoderServiceGrpc
import com.viam.component.encoder.v1.EncoderServiceGrpc.EncoderServiceBlockingStub
import com.viam.sdk.core.rpc.Channel
import java.util.*
import kotlin.jvm.optionals.getOrDefault

class EncoderRPCClient(name: String, channel: Channel) : Encoder(name) {
private val client: EncoderServiceBlockingStub

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

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

override fun getPosition(positionType: PositionType?, extra: Struct): Pair<Float, PositionType> {
val request = GetPositionRequest.newBuilder().setName(this.name.name).setExtra(extra)
if (positionType != null) {
request.setPositionType(positionType)
}
val response = this.client.getPosition(request.build())
return (response.value to response.positionType)

}

override fun getProperties(extra: Struct): Properties {
val request = GetPropertiesRequest.newBuilder().setName(this.name.name).setExtra(extra).build()
return this.client.getProperties(request)
}

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,75 @@
package com.viam.sdk.core.component.encoder

import com.viam.common.v1.Common.*
import com.viam.component.encoder.v1.Encoder.*
import com.viam.component.encoder.v1.EncoderServiceGrpc
import com.viam.sdk.core.component.encoder.Encoder
import com.viam.sdk.core.resource.ResourceManager
import com.viam.sdk.core.resource.ResourceRPCService
import io.grpc.stub.StreamObserver
import java.util.*

internal class EncoderRPCService(private val manager: ResourceManager) : EncoderServiceGrpc.EncoderServiceImplBase(),
ResourceRPCService<Encoder> {

override fun resetPosition(
request: ResetPositionRequest,
responseObserver: StreamObserver<ResetPositionResponse>
) {
val encoder = getResource(Encoder.named(request.name))
encoder.resetPosition(request.extra)
responseObserver.onNext(ResetPositionResponse.newBuilder().build())
responseObserver.onCompleted()
}

override fun getPosition(request: GetPositionRequest, responseObserver: StreamObserver<GetPositionResponse>) {
val encoder = getResource(Encoder.named(request.name))
val position: Pair<Float, PositionType> = if (request.hasPositionType())
encoder.getPosition(request.positionType, request.extra)
else
encoder.getPosition(request.extra)
responseObserver.onNext(
GetPositionResponse.newBuilder().setPositionType(position.second).setValue(position.first).build()
)
responseObserver.onCompleted()
}

override fun getProperties(
request: GetPropertiesRequest,
responseObserver: StreamObserver<GetPropertiesResponse>
) {
val encoder = getResource(Encoder.named(request.name))
val properties = encoder.getProperties(request.extra)
responseObserver.onNext(
GetPropertiesResponse.newBuilder().setTicksCountSupported(properties.ticksCountSupported)
.setAngleDegreesSupported(properties.angleDegreesSupported).build()
)
responseObserver.onCompleted()
}

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

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

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

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

0 comments on commit 698114b

Please sign in to comment.