初步完成

This commit is contained in:
LiXiaoqi 2024-10-12 14:04:26 +08:00
parent b38c834818
commit 627c1c925a
5 changed files with 149 additions and 3 deletions

View File

@ -38,14 +38,16 @@ class _MyHomePageState extends State<MyHomePage> {
int msgToPublished = 0; int msgToPublished = 0;
@override @override
void initState() { void initState() {
ros = Ros(url: 'ws://127.0.0.1:9090'); ros = Ros(url: 'ws://192.168.1.149:9090');
service = Service( service = Service(
name: 'add_two_ints', ros: ros, type: "tutorial_interfaces/AddTwoInts"); name: '/add_two_ints', ros: ros, type: "/tutorial_interfaces/AddTwoInts");
super.initState(); super.initState();
ros.connect(); ros.connect();
Timer(const Duration(seconds: 3), () async { Timer(const Duration(seconds: 3), () async {
await service.advertise(serviceHandler); // await service.advertise(serviceHandler);
var res = await service.call({'a': 1, 'b': 2});
print(res);
}); });
} }

View File

@ -5,6 +5,9 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST}) foreach(plugin ${FLUTTER_PLUGIN_LIST})
@ -13,3 +16,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin) endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)

128
lib/core/action.dart Normal file
View File

@ -0,0 +1,128 @@
import 'dart:async';
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'ros.dart';
import 'request.dart';
import 'dart:math';
typedef ActionHandler = void Function(Map<String, dynamic> response);
typedef UUID = List;
class GoalHandle {
ActionHandler onSendGoal;
ActionHandler onFeedback;
ActionHandler onResult;
GoalHandle({
required this.onSendGoal,
required this.onFeedback,
required this.onResult,
});
}
// goal都要构造Action
class Action {
Ros ros;
String name;
String type;
// goal时uuidcancel_goal
Map<String, List<num>> uuids = {};
StreamSubscription? goalListener;
StreamSubscription? feedbackListener;
StreamSubscription? resultListener;
StreamSubscription? cancelListener;
GoalHandle goalHandle;
Action({
required this.name,
required this.ros,
required this.type,
required this.goalHandle,
});
List<num> generateRandomString(int length) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
Random random = Random();
return List.generate(length, (index) {
return characters[random.nextInt(characters.length)].codeUnitAt(0);
});
}
void _bindFeedbackAndResult(String callId) {
final feedbackLis = ros.stream;
feedbackLis.listen((message) {
goalHandle.onFeedback(message);
});
final resultReceiver = ros.stream.where((message) => message['op'] == 'action_result' && message['id'] == callId)
.map((Map<String, dynamic> message) => message['result'] == null
? message['values']!
: message['values']);
resultListener = resultReceiver.listen((d) {
goalHandle.onResult(d);
resultListener!.cancel();
});
}
String sendGoal(dynamic req) {
final callId = ros.requestServiceCaller(name);
final completer = Completer<List>();
final uuid = generateRandomString(16);
var reqObj = Request(
op: 'send_action_goal',
id: callId,
action: req['action'],
type: req['type'],
args: {
"goal_id" : {
"uuid": uuid,
},
"goal": req['args'],
},
);
if (uuids.containsKey(callId)) {
uuids[callId] = uuid;
} else {
uuids.addAll({callId: uuid});
}
ros.send(reqObj);
final receiver = ros.stream.where((message) {
return message['id'] == callId && message['op'] != 'cancel_goal_response';
} );
goalListener = receiver.listen((d) {
if (d["op"] == "action_result") {
goalHandle.onResult(d);
goalListener!.cancel();
} else if (d["op"] == "action_feedback") {
goalHandle.onFeedback(d);
} else if (d["op"] == 'send_goal_response') {
completer.complete(uuids[callId]);
goalHandle.onSendGoal(d);
}
});
return callId;
}
Future cancelGoal(dynamic req, String callId, ActionHandler onCancel) {
final completer = Completer();
var cancelReq = Request(
op: 'cancel_action_goal',
id: callId,
action: req['action'],
);
print("cancelReq: ${cancelReq.toJson()}");
ros.send(cancelReq);
final receiver = ros.stream.where(
(message) => message['id'] == callId && message['op'] == 'cancel_goal_response'
);
cancelListener = receiver.listen((d) {
onCancel(d);
completer.complete();
cancelListener!.cancel();
});
return completer.future;
}
}

View File

@ -5,3 +5,4 @@ export 'request.dart';
export 'service.dart'; export 'service.dart';
export 'topic.dart'; export 'topic.dart';
export 'param.dart'; export 'param.dart';
export 'action.dart';

View File

@ -16,6 +16,7 @@ class Request {
this.queueLength, this.queueLength,
this.queueSize, this.queueSize,
this.service, this.service,
this.action,
this.args, this.args,
this.values, this.values,
this.result, this.result,
@ -54,6 +55,9 @@ class Request {
/// Service name operating on. /// Service name operating on.
String? service; String? service;
/// action name operating on.
String? action;
/// Arguments of the request (JSON). /// Arguments of the request (JSON).
Map<String, dynamic>? args; Map<String, dynamic>? args;
@ -66,10 +70,12 @@ class Request {
factory Request.fromJson(dynamic jsonData) { factory Request.fromJson(dynamic jsonData) {
return Request( return Request(
op: jsonData['op'], op: jsonData['op'],
// type: jsonData['type'],
id: jsonData['id'], id: jsonData['id'],
type: jsonData['type'], type: jsonData['type'],
topic: jsonData['topic'], topic: jsonData['topic'],
msg: jsonData['msg'], msg: jsonData['msg'],
action: jsonData['action'],
latch: jsonData['latch'], latch: jsonData['latch'],
compression: jsonData['compression'], compression: jsonData['compression'],
throttleRate: jsonData['throttle_rate'], throttleRate: jsonData['throttle_rate'],
@ -99,6 +105,7 @@ class Request {
if (queueLength != null) 'queue_length': queueLength, if (queueLength != null) 'queue_length': queueLength,
if (queueSize != null) 'queue_size': queueSize, if (queueSize != null) 'queue_size': queueSize,
if (service != null) 'service': service, if (service != null) 'service': service,
if (action != null) 'action': action,
if (args != null) 'args': args, if (args != null) 'args': args,
if (values != null) 'values': values, if (values != null) 'values': values,
if (result != null) 'result': result, if (result != null) 'result': result,