Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 10 additions & 0 deletions lib/src/components/arm/arm.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import '../../../viam_sdk.dart';
import '../../gen/common/v1/common.pb.dart';
import '../../utils.dart';

/// {@category Components}
/// Arm represents a physical robot arm that exists in three-dimensional space.
Expand Down Expand Up @@ -88,6 +89,15 @@ abstract class Arm extends Resource {
/// For more information, see [Arm component](https://docs.viam.com/dev/reference/apis/components/arm/#getkinematics).
Future<Kinematics> getKinematics({Map<String, dynamic>? extra});

/// Get all geometries associated with the [Arm]
///
/// ```
/// final geometries = await myArm.getGeometries();
/// ```
///
/// For more information, see [Arm component](https://docs.viam.com/dev/reference/apis/components/arm/#getgeometries).
Future<List<Geometry>> getGeometries({Map<String, dynamic>? extra});

/// Get the [ResourceName] for this [Arm] with the given [name].
///
/// ```
Expand Down
10 changes: 9 additions & 1 deletion lib/src/components/arm/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import '../../gen/component/arm/v1/arm.pbgrpc.dart';
import '../../gen/google/protobuf/struct.pb.dart';
import '../../resource/base.dart';
import '../../utils.dart';
import '../gripper/gripper.dart';
import 'arm.dart';

/// {@category Components}
Expand Down Expand Up @@ -101,4 +100,13 @@ class ArmClient extends Arm with RPCDebugLoggerMixin implements ResourceRPCClien
final response = await client.getKinematics(request, options: callOptions);
return Kinematics.fromProto(response);
}

@override
Future<List<Geometry>> getGeometries({Map<String, dynamic>? extra}) async {
final request = GetGeometriesRequest()
..name = name
..extra = extra?.toStruct() ?? Struct();
final response = await client.getGeometries(request, options: callOptions);
return response.geometries;
}
}
7 changes: 4 additions & 3 deletions lib/src/components/arm/service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ class ArmService extends ArmServiceBase {
}

@override
Future<GetGeometriesResponse> getGeometries(ServiceCall call, GetGeometriesRequest request) {
// TODO: implement getGeometries
throw UnimplementedError();
Future<GetGeometriesResponse> getGeometries(ServiceCall call, GetGeometriesRequest request) async {
final arm = _armFromManager(request.name);
final geometries = await arm.getGeometries(extra: request.extra.toMap());
return GetGeometriesResponse()..geometries.addAll(geometries);
}

@override
Expand Down
18 changes: 18 additions & 0 deletions lib/src/components/gantry/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,22 @@ class GantryClient extends Gantry with RPCDebugLoggerMixin implements ResourceRP
final response = await client.doCommand(request, options: callOptions);
return response.result.toMap();
}

@override
Future<Kinematics> getKinematics({Map<String, dynamic>? extra}) async {
final request = GetKinematicsRequest()
..name = name
..extra = extra?.toStruct() ?? Struct();
final response = await client.getKinematics(request, options: callOptions);
return Kinematics.fromProto(response);
}

@override
Future<List<Geometry>> getGeometries({Map<String, dynamic>? extra}) async {
final request = GetGeometriesRequest()
..name = name
..extra = extra?.toStruct() ?? Struct();
final response = await client.getGeometries(request, options: callOptions);
return response.geometries;
}
}
19 changes: 19 additions & 0 deletions lib/src/components/gantry/gantry.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '../../gen/common/v1/common.pb.dart';
import '../../resource/base.dart';
import '../../robot/client.dart';
import '../../utils.dart';

/// {@category Components}
/// Gantry represents a physical Gantry and can be used for controlling gantries of N axes.
Expand Down Expand Up @@ -63,6 +64,24 @@ abstract class Gantry extends Resource {
/// For more information, see [Gantry component](https://docs.viam.com/dev/reference/apis/components/gantry/#ismoving).
Future<bool> isMoving();

/// Get the kinematics data associated with the [Gantry]
///
/// ```
/// var kinematics = await myGantry.getKinematics();
/// ```
///
/// For more information, see [Gantry component](https://docs.viam.com/dev/reference/apis/components/gantry/#getkinematics).
Future<Kinematics> getKinematics({Map<String, dynamic>? extra});

/// Get all geometries associated with the [Gantry]
///
/// ```
/// final geometries = await myGantry.getGeometries();
/// ```
///
/// For more information, see [Gantry component](https://docs.viam.com/dev/reference/apis/components/gantry/#getgeometries).
Future<List<Geometry>> getGeometries({Map<String, dynamic>? extra});

/// Get the [ResourceName] for this [Gantry] with the given [name]
///
/// ```
Expand Down
16 changes: 10 additions & 6 deletions lib/src/components/gantry/service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,18 @@ class GantryService extends GantryServiceBase {
}

@override
Future<GetGeometriesResponse> getGeometries(ServiceCall call, GetGeometriesRequest request) {
// TODO: implement getGeometries
throw UnimplementedError();
Future<GetGeometriesResponse> getGeometries(ServiceCall call, GetGeometriesRequest request) async {
final gantry = _fromManager(request.name);
final geometries = await gantry.getGeometries(extra: request.extra.toMap());
return GetGeometriesResponse()..geometries.addAll(geometries);
}

@override
Future<GetKinematicsResponse> getKinematics(ServiceCall call, GetKinematicsRequest request) {
// TODO: implement getKinematics
throw UnimplementedError();
Future<GetKinematicsResponse> getKinematics(ServiceCall call, GetKinematicsRequest request) async {
final gantry = _fromManager(request.name);
final response = await gantry.getKinematics(extra: request.extra.toMap());
return GetKinematicsResponse()
..format = response.format
..kinematicsData = response.raw;
}
}
12 changes: 0 additions & 12 deletions lib/src/components/gripper/gripper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@ import '../../resource/base.dart';
import '../../robot/client.dart';
import '../../utils.dart';

/// {@category Viam SDK}
class Kinematics {
KinematicsFileFormat format;
List<int> raw;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seemed weird to import a class from another component (gripper -> arm and gripper -> gantry) so I moved it into the utils.dart which seems to have common component utils. Couldn't find anything online about it being a flutter convention? lmk if it should be kept here


Kinematics(this.format, this.raw);

factory Kinematics.fromProto(GetKinematicsResponse gkResponse) {
return Kinematics(gkResponse.format, gkResponse.kinematicsData);
}
}

/// {@category Viam SDK}
/// HoldingStatus represents whether the gripper is currently holding onto
/// an object as well as any additional contextual information (stored in `Meta`).
Expand Down
11 changes: 11 additions & 0 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ import 'gen/google/protobuf/struct.pb.dart';

final _logger = Logger();

class Kinematics {
KinematicsFileFormat format;
List<int> raw;

Kinematics(this.format, this.raw);

factory Kinematics.fromProto(GetKinematicsResponse gkResponse) {
return Kinematics(gkResponse.format, gkResponse.kinematicsData);
}
}

extension NullableStringUtils on String? {
bool get isNullOrEmpty {
return this?.isEmpty ?? true;
Expand Down
64 changes: 56 additions & 8 deletions test/unit_test/components/arm_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ class FakeArm extends Arm {
Map<String, dynamic>? extra;
Map<String, Mesh> arm3DModels = {};
Kinematics armKinematics = Kinematics(KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA, [1, 2, 3]);

List<Geometry> armGeometries = [
Geometry()
..box = (RectangularPrism()
..dimsMm = (Vector3()
..x = 1
..y = 2
..z = 3)),
];
@override
String name;

Expand Down Expand Up @@ -74,6 +81,12 @@ class FakeArm extends Arm {
return arm3DModels;
}

@override
Future<List<Geometry>> getGeometries({Map<String, dynamic>? extra}) async {
this.extra = extra;
return armGeometries;
}

@override
Future<Kinematics> getKinematics({Map<String, dynamic>? extra}) async {
this.extra = extra;
Expand Down Expand Up @@ -154,6 +167,14 @@ void main() {
expect(arm.extra, {'foo': 'bar'});
});

test('getGeometries', () async {
final geometries = await arm.getGeometries();
expect(geometries[0].whichGeometryType(), Geometry_GeometryType.box);
expect(geometries[0].box.dimsMm.x, 1);
expect(geometries[0].box.dimsMm.y, 2);
expect(geometries[0].box.dimsMm.z, 3);
});

test('getKinematics', () async {
final kinematics = await arm.getKinematics();
expect(kinematics.format, KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA);
Expand All @@ -175,7 +196,11 @@ void main() {
service = ArmService(manager);
server = Server.create(services: [service]);
await serveServerAtUnusedPort(server);
channel = ClientChannel('localhost', port: server.port!, options: const ChannelOptions(credentials: ChannelCredentials.insecure()));
channel = ClientChannel(
'localhost',
port: server.port!,
options: const ChannelOptions(credentials: ChannelCredentials.insecure()),
);
});

tearDown(() async {
Expand Down Expand Up @@ -262,19 +287,23 @@ void main() {
final cmd = {'foo': 'bar'};

final client = ArmServiceClient(channel);
final resp = await client.doCommand(DoCommandRequest()
..name = name
..command = cmd.toStruct());
final resp = await client.doCommand(
DoCommandRequest()
..name = name
..command = cmd.toStruct(),
);
expect(resp.result.toMap()['command'], cmd);
});

test('extra', () async {
expect(arm.extra, null);

final client = ArmServiceClient(channel);
await client.stop(StopRequest()
..name = name
..extra = {'foo': 'bar'}.toStruct());
await client.stop(
StopRequest()
..name = name
..extra = {'foo': 'bar'}.toStruct(),
);
expect(arm.extra, {'foo': 'bar'});
});

Expand All @@ -285,6 +314,16 @@ void main() {
expect(response.format, KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA);
expect(response.kinematicsData, [1, 2, 3]);
});

test('getGeometries', () async {
final client = ArmServiceClient(channel);
final request = GetGeometriesRequest()..name = name;
final response = await client.getGeometries(request);
expect(response.geometries[0].whichGeometryType(), Geometry_GeometryType.box);
expect(response.geometries[0].box.dimsMm.x, 1);
expect(response.geometries[0].box.dimsMm.y, 2);
expect(response.geometries[0].box.dimsMm.z, 3);
});
});

group('Arm Client Tests', () {
Expand Down Expand Up @@ -365,5 +404,14 @@ void main() {
expect(kinematics.format, KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA);
expect(kinematics.raw, [1, 2, 3]);
});

test('getGeometries', () async {
final client = ArmClient(name, channel);
final geometries = await client.getGeometries();
expect(geometries[0].whichGeometryType(), Geometry_GeometryType.box);
expect(geometries[0].box.dimsMm.x, 1);
expect(geometries[0].box.dimsMm.y, 2);
expect(geometries[0].box.dimsMm.z, 3);
});
});
}
Loading