-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathASDP_Core_API.h
More file actions
2939 lines (2453 loc) · 139 KB
/
Copy pathASDP_Core_API.h
File metadata and controls
2939 lines (2453 loc) · 139 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (C) 2024: Arizona Board of Regents on Behalf of the University of Arizona
*/
#pragma once
/**
* @file ASDP_Core_API.h
* @brief Apache Strap-Down Pilotage Core C++ API exposed as a static library.
*
* @author ReliaSolve.
* @date January 22, 2024.
*/
//----------------------------------------------------------------------------------------
// Include the configuration file that defines the import or export for DLLs on Windows.
// These are left undefined on other platforms. The CMake system adds a definition that
// causes export when the library is built and import for other applications.
#include <cstdint>
#include <string>
#include <chrono>
#include <memory>
#include <vector>
#include <fstream>
#include <thread>
#include <atomic>
#include <mutex>
#include <array>
#include <list>
#include <map>
#include <ostream>
namespace asdp {
//---------------------------------------------------------------------------
/// @brief Status enumeration, returned by API functions.
enum Status : uint32_t {
/// @brief All is okay.
OKAY = 0,
/// @brief A timeout was exceeded (not an error).
TIMEOUT = 1,
/// @brief A thread has completed its work (not an error).
THREAD_COMPLETED = 2,
/// @brief Can be used to see if the return was a system error.
HIGHEST_WARNING = 1000,
/// @brief Error: Bad parameter passed to function.
BAD_PARAMETER = 1001,
/// @brief Error: Out of memory when trying to execute function.
OUT_OF_MEMORY = 1002,
/// @brief Error: Function not yet implemented.
NOT_IMPLEMENTED = 1003,
/// @brief Error: Attempting to delete an object failed.
DELETION_FAILED = 1004,
/// @brief Error: Internal failure: calling an object with a NULL object pointer.
NULL_OBJECT_POINTER = 1005,
/// @brief Error: Internal failure: Exception inside the implementation.
INTERNAL_EXCEPTION = 1006,
/// @brief Error: Socket error.
SOCKET_FAILURE = 1007,
/// @brief Error: Attempting to read past the memory available in an object.
READ_PAST_END = 1008,
/// @brief Error: Bad magic cookie in packet.
BAD_COOKIE = 1009,
/// @brief Error: Attempting to write past the memory available in an object.
WRITE_PAST_END = 1010,
/// @brief Error: Buffer too small to receive packet or other issue.
SOCKET_READ_FAILURE = 1011,
/// @brief File error
FILE_FAILURE = 1012,
/// @brief Error: Unexpected internal state.
UNEXPECTED_INTERNAL_STATE = 1013,
/// @brief The endianness on this architecture is incorrect
INCORRECT_ENDIANNESS = 1014,
/// @brief Error: The object is not connected to a counterpart objects.
NOT_CONNECTED = 1015,
/// @brief Error: The size of a floating-point number is not what was expected.
INCORRECT_FLOAT_SIZE = 1016,
/// @brief Error: Incompatible version of the API.
INCOMPATIBLE_API_VERSION = 1017
};
/// @brief Helper function to return a descriptive error message based on a status value.
/// @param [in] status Status value returned from an API call.
/// @return String describing the status condition.
std::string ErrorMessage(Status status);
//---------------------------------------------------------------------------
/// @brief Operation codes for command packets.
enum OpCode : uint32_t {
RESET = 0,
START_RECORDING = 2,
STOP_RECORDING = 3,
START_REPLAY = 4,
PAUSE_REPLAY = 5,
RESUME_REPLAY = 6,
STOP_REPLAY = 7,
SET_START_UP_RECORDING_STATE = 8,
SET_STREAM_STATE_PERIOD = 10,
SET_NUC_FLAG_STATE = 11,
START_ON_CAMERA_NUC = 12,
CONFIGURE_TRIGGER = 10000,
SOFTWARE_TRIGGER = 10001,
SET_EVENT_VERBOSITY = 10002,
STREAM_SUBREGION = 20000,
CANCEL_SUBREGION = 20001,
ERASE_ALL_STORED_STREAMS = 30000,
LIST_STORED_STREAMS = 30001,
ERASE_STORED_STREAM = 30002,
STREAM_TEMPERATURES = 40000,
CANCEL_TEMPERATURES = 40001,
STREAM_POSES = 50000,
CANCEL_POSES = 50001
};
//---------------------------------------------------------------------------
/// @brief Message IDs for stream packets.
enum MessageID : uint32_t {
DISCOVERY = 0,
STATE = 1,
EVENT = 10000,
//FRAME_BEGIN = 20000,
//FRAME_DATA = 20001,
//FRAME_END = 20002,
CONSOLIDATED_FRAME_DATA = 20003,
STORED_STREAMS = 30000,
TEMPERATURE = 40000,
POSE = 50000
};
//---------------------------------------------------------------------------
/// @brief Event IDs. These are sent on the main command stream.
enum EventID : uint32_t {
INVALID_OPERATION = 256, // String parameter with bad opcode.
INTERNAL_ERROR = 257,
UNRECOGNIZED_OPCODE = 512, // String parameter with bad opcode.
CLOCK_SYNC = 768,
START_OF_REPLAY = 769,
END_OF_REPLAY = 770,
NUC_FLAG_STATE = 771, // String parameter with CAMERA_ID,FLAG_STATE (0=off, 1=on)
ON_CAMERA_NUC_STATE = 772, // String parameter with CAMERA_ID,NUC_STATE (0=off, 1=on)
REPLAY_PAUSED = 773,
REPLAY_RESUMED = 774,
};
//---------------------------------------------------------------------------
/// @brief feature IDs.
enum FeatureID : uint16_t {
STORAGE_API_AVAILABLE = 1,
TEMPERATURE_API_AVAILABLE = 3,
POSE_API_ORIENTATION_AVAILABLE = 4,
POSE_API_POSITION_AVAILABLE = 5,
NUC_FLAG_AVAILABLE = 6,
ON_CAMERA_NUC_AVAILABLE = 7
};
//---------------------------------------------------------------------------
/// @brief Class to store information about a camera.
class CameraInfo {
public:
double minTriggerPeriod; ///< Minimum period between triggers in seconds.
double maxTriggerPeriod; ///< Maximum period between triggers in seconds.
uint32_t trigger; ///< Internal hardware trigger ID camera is tied to (0 = none).
uint32_t type; ///< Type of camera (used to look up lens, sensors, etc. in a table)
uint16_t width; ///< Width of the camera image in pixels.
uint16_t height; ///< Height of the camera image in pixels.
/// @brief Equality operator.
bool operator ==(const CameraInfo& other) const {
return type == other.type &&
width == other.width &&
height == other.height &&
minTriggerPeriod == other.minTriggerPeriod &&
maxTriggerPeriod == other.maxTriggerPeriod &&
trigger == other.trigger;
};
/// @brief Inequality operator.
bool operator !=(const CameraInfo& other) const {
return !(*this == other);
};
};
//---------------------------------------------------------------------------
/// @brief Class to store information about a trigger configuration.
class TriggerInfo {
public:
double period; ///< Period of the trigger in seconds.
float offset; ///< Offset of the trigger in seconds. A positive offset will cause the local hardware trigger to fire later than the incoming trigger command. Negative values are clamped to 0.
float trackingFactor; ///< Tracking factor of the trigger. Value in range [0-1] telling fraction of discrepancy to correct when synchronizing with a new incoming trigger. A value of 1 completely synchronizes with each trigger. A value of 0.1 shifts by 1 / 10th of the distance, smoothing the adjustment to handle jitter in the incoming hardware trigger while following long-time-scale drift.
uint16_t ID; ///< ID of the trigger.
uint8_t mode; ///< Mode of the trigger (0 = disabled, 1 = unsynchronized, 2 = one-shot software, 3 = periodic software, 4 = one-shot hardware, 5 = periodic hardware).
uint8_t externalID; ///< ID of the external trigger to use (0 = none).
/// @brief Equality operator.
bool operator ==(const TriggerInfo& other) const {
return ID == other.ID &&
mode == other.mode &&
externalID == other.externalID &&
period == other.period &&
offset == other.offset &&
trackingFactor == other.trackingFactor;
}
/// @brief Inequality operator.
bool operator !=(const TriggerInfo& other) const {
return !(*this == other);
}
};
//---------------------------------------------------------------------------
/// @brief Class to store information about a stream endpoint.
/// @brief Class to store information about a stream endpoint.
class StreamEndpoint {
public:
/// @brief Construct a stream endpoint from an IP address and port.
/// @param [in] IP IP address being streamed to in host byte order.
/// @param [in] port Port being streamed to in host byte order.
StreamEndpoint(uint32_t IP, uint16_t port) : IP(IP), port(port) { };
/// @brief Construct a stream endpoint from a host name/IP and port.
/// @param [in] host Host name or IP address being streamed to. Sets
/// the IP to 0 if the host name is not a valid name or IP address.
/// Sets it to INADDR_ANY (which is also 0) if the host name is "".
/// @param [in] port Port being streamed to in host byte order.
StreamEndpoint(const std::string &host, uint16_t port);
/// @brief default constructor
StreamEndpoint() : IP(0), port(0) { };
uint32_t IP; ///< IP being streamed to in host byte order
uint16_t port; ///< Port being streamed to in host byte order
/// @brief Equality operator.
bool operator ==(const StreamEndpoint& other) const {
return IP == other.IP && port == other.port;
}
/// @brief Inequality operator.
bool operator !=(const StreamEndpoint& other) const {
return !(*this == other);
}
/// @brief less-than operator.
bool operator <(const StreamEndpoint& other) const {
return IP < other.IP || (IP == other.IP && port < other.port);
}
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
//---------------------------------------------------------------------------
/// @brief Class to store seconds and microseconds since the epoch, matching Linux gettimeofday().
struct Time {
public:
uint32_t seconds; ///< Seconds portion of time since the start of the epoch.
uint32_t microseconds; ///< Microseconds portion of time since the start of the epoch.
/// @brief Equality operator.
bool operator ==(const Time& other) const {
return seconds == other.seconds && microseconds == other.microseconds;
};
/// @brief Inequality operator.
bool operator !=(const Time& other) const {
return !(*this == other);
};
/// @brief Less-than operator.
bool operator <(const Time& other) const {
return seconds < other.seconds || (seconds == other.seconds && microseconds < other.microseconds);
};
/// @brief Less-than-or-equal operator.
bool operator <=(const Time& other) const {
return seconds < other.seconds || (seconds == other.seconds && microseconds <= other.microseconds);
};
/// @brief Greater-than operator.
bool operator >(const Time& other) const {
return seconds > other.seconds || (seconds == other.seconds && microseconds > other.microseconds);
};
/// @brief Greater-than-or-equal operator.
bool operator >=(const Time& other) const {
return seconds > other.seconds || (seconds == other.seconds && microseconds >= other.microseconds);
};
/// @brief Add operator.
Time operator +(const Time& other) const {
Time result = { seconds + other.seconds, microseconds + other.microseconds };
if (result.microseconds >= 1000000) {
result.seconds++;
result.microseconds -= 1000000;
}
return result;
};
/// @brief Subtract operator.
Time operator -(const Time& other) const {
Time result = { seconds - other.seconds, microseconds };
if (result.microseconds < other.microseconds) {
result.seconds--;
result.microseconds += 1000000;
}
result.microseconds -= other.microseconds;
return result;
};
/// @brief Add-assign operator.
Time& operator +=(const Time& other) {
seconds += other.seconds;
microseconds += other.microseconds;
if (microseconds >= 1000000) {
seconds++;
microseconds -= 1000000;
}
return *this;
};
/// @brief Subtract-assign operator.
Time& operator -=(const Time& other) {
seconds -= other.seconds;
if (microseconds < other.microseconds) {
seconds--;
microseconds += 1000000;
}
microseconds -= other.microseconds;
return *this;
};
/// @brief Set to a floating-point value in seconds.
Time& operator =(float value) {
if (value < 0) {
seconds = 0;
microseconds = 0;
} else {
seconds = static_cast<uint32_t>(value);
microseconds = static_cast<uint32_t>((value - seconds) * 1000000);
}
return *this;
}
/// @brief Construct with a floating-point value in seconds.
Time(float value) {
*this = value;
}
/// @brief Construct with two values, normalizing microseconds to less than 1,000,000.
Time(uint32_t sec, uint32_t usec) : seconds(sec + usec / 1000000), microseconds(usec % 1000000) { }
/// @brief Default constructor
Time() : seconds(0), microseconds(0) {};
};
//---------------------------------------------------------------------------
/// @brief Class to report the time on the Core based on local time. Must be constructed by Core.
class Timer {
public:
/// @brief Virtual destructor so all derived class pointers will destroy properly.
virtual ~Timer();
/// @brief Get the Core time corresponding to the specified local steady_clock time.
/// @param [out] core_time The Core time corresponding to the specified local time.
/// @param [in] local_time The local time to convert. Defaults to the current time.
/// Note that the steady_clock might bear no relationship to wall-clock time. It is
/// guaranteed to have uniform ticks, but the client is responsible for converting
/// to system_clock if that is desired (note that system_clock may vary in rate and
/// may have discontinuous jumps forwards and backwards).
/// @return OKAY if successful, otherwise an error code.
Status GetCoreTime(Time& core_time,
const std::chrono::steady_clock::time_point local_time = std::chrono::steady_clock::now()) const;
/// @brief Set the offset between Core time and local time, subtracted from local time.
/// @details Note that both negative and positive offsets can be provided. The Core time
/// is localtime + positive offset - negative offset. This helps with clock synchronization.
/// @param [in] offset Offset between Core time and local time.
/// @return OKAY if successful, otherwise an error code.
/// Returns BAD_PARAMETER if the offset is too large.
Status SetCoreNegativeOffset(Time offset);
/// @brief Set the offset between Core time and local time, added to local time.
/// @details Note that both negative and positive offsets can be provided. The Core time
/// is localtime + positive offset - negative offset. This helps with clock synchronization.
/// @param [in] offset Offset between Core time and local time.
/// @return OKAY if successful, otherwise an error code.
/// Returns BAD_PARAMETER if the offset is too large.
Status SetCorePositiveOffset(Time offset);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
protected:
Timer();
Timer(const Timer&) = delete;
Timer& operator=(const Timer&) = delete;
Timer(Timer&&) = delete;
Timer& operator=(Timer&&) = delete;
Time m_coreNegativeOffset; ///< Offset subtracted from local time to get Core time.
Time m_corePositiveOffset; ///< Offset added to Core time to get local time.
friend class StreamWriter; // So it can implement Test().
friend class Core;
friend class ClockSynchronizer; // So it can implement Test().
};
//---------------------------------------------------------------------------
/// @brief Base packet type, not used by calling program, supports code common to CommandPacket and StreamPacket.
///
/// The GetConstructorStatus() function can be used to determine if the constructor was successful
/// in this class and in derived classes.
class BasicPacket {
public:
/// @brief Return the status of the constructor.
Status GetConstructorStatus() const;
/// @brief Return the total length of the packet.
Status GetTotalLength(uint32_t &totalLength) const;
/// @brief Virtual destructor so all derived class pointers will destroy properly.
virtual ~BasicPacket();
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
protected:
// Remove the default constructor and copy operators.
BasicPacket() = delete;
BasicPacket(const BasicPacket&) = delete;
BasicPacket& operator=(const BasicPacket&) = delete;
BasicPacket(BasicPacket&&) = delete;
BasicPacket& operator=(BasicPacket&&) = delete;
/// @brief Construct a basic packet with its own buffer and fill its values in.
/// @param [in] extraSize Size of the packet beyond the basic packet size.
/// This includes all extra header information and the parameter portion of the packet.
BasicPacket(uint32_t extraSize);
/// @brief Construct a basic packet that shares a buffer with another packet.
///
/// This is used when type-casting from an existing buffer to a subclass.
/// It is also used when constructing a new packet from an existing buffer
/// that was received from the network.
///
/// @param [in] existingBuffer Pointer to the buffer containing the packet information.
/// This adds a reference count to the buffer to ensure that it is not deleted out from
/// under us.
/// @param [in] offset Offset into the buffer to start at. This supports having multiple
/// packets in the same buffer
BasicPacket(std::shared_ptr<std::vector<uint8_t>> existingBuffer, size_t offset = 0);
/// @brief Increase total length of the packet (used by Messages when inserting themselves).
/// @param [in] addedSize Additional size.
/// @return OKAY if successful, otherwise an error code.
Status IncreaseTotalLength(uint32_t addedSize);
/// @brief Get the remaining free space in our buffer.
size_t MyRemainingSize() const { return m_buffer->size() - m_offset; }
/// @brief Get the remaining allocated space in our buffer.
size_t MyRemainingCapacity() const { return m_buffer->capacity() - m_offset; }
/// @brief Get the buffer containing the packet data at the appropriate offset.
std::uint8_t *MyData() const { return m_buffer->data() + m_offset; }
/// @brief Adjust an offset in the buffer to align with the start of the packet.
size_t AddOffset(size_t offset) const { return offset + m_offset; }
/// @brief Adjust an offset in the buffer to align with the start of the packet.
size_t RemoveOffset(size_t offset) const { return offset - m_offset; }
std::shared_ptr<std::vector<uint8_t>> m_buffer; ///< Buffer containing the packet.
size_t m_offset; ///< Offset into the buffer to start at.
Status m_constructorStatus; ///< Status of the constructor.
friend class CommandPacket;
friend class StreamPacket;
};
//---------------------------------------------------------------------------
/// @brief Command packet, subclass constructed and sent by clients and received and parsed by server.
///
/// The command packet is a command sent by a client to a server. It contains an operation code
/// and optional parameters. The server receives the packet, parses it, and executes the operation.
/// These packets are sent using the Sender class and received using the Receiver class.
/// They are created on a client by constructing a subclass. They are parsed on a server from a
/// buffer by checking the operation code and then typecasting to the appropriate subclass.
///
/// There can only be one CommandPacket per buffer, so the offset in the BasicPacket is always 0.
///
/// Subclasses are listed below.
class CommandPacket : public BasicPacket {
public:
/// @brief Get the operation code for this command packet.
/// @param [out] opCode The operation code for this command packet.
/// @return OKAY if successful, otherwise an error code.
Status GetOpCode(OpCode& opCode) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
protected:
// Remove the default constructor and copy operators.
CommandPacket() = delete;
CommandPacket(const CommandPacket&) = delete;
CommandPacket& operator=(const CommandPacket&) = delete;
CommandPacket(CommandPacket&&) = delete;
CommandPacket& operator=(CommandPacket&&) = delete;
/// @brief Construct a command packet with its own buffer and fill its values in.
/// @param [in] parameterSize Size of the parameter portion of the packet.
/// @param [in] code Operation code for the packet.
CommandPacket(uint32_t parameterSize, OpCode code);
/// @brief Construct a command packet that shares a buffer with another packet.
///
/// It is used when constructing a new packet from an existing buffer
/// that was received from the network.
///
/// @param [in] existingBuffer Pointer to the buffer containing the packet information.
/// This adds a reference count to the buffer to ensure that it is not deleted out from
/// under us.
CommandPacket(std::shared_ptr<std::vector<uint8_t>> existingBuffer);
/// @brief Construct a command packet that shares a buffer with another packet.
///
/// This is used when type-casting from an existing buffer to a subclass.
/// It verifies that the buffer contains the correct type of packet.
///
/// @param [in] existingBuffer Pointer to the buffer containing the packet information.
/// @param [in] code Operation code for the packet. Used to verify that the buffer contains the correct type of packet.
/// This adds a reference count to the buffer to ensure that it is not deleted out from
/// under us.
CommandPacket(std::shared_ptr<std::vector<uint8_t>> existingBuffer, OpCode code);
friend class SenderUDP;
friend class SenderFile;
friend class ReceiverUDP;
friend class ReceiverFile;
friend class SenderReceiverTCP;
friend class CommandPacketReset;
friend class CommandPacketStartRecording;
friend class CommandPacketStopRecording;
friend class CommandPacketStartReplay;
friend class CommandPacketPauseReplay;
friend class CommandPacketResumeReplay;
friend class CommandPacketStopReplay;
friend class CommandPacketSetStartUpRecordingState;
friend class CommandPacketSetStreamStatePeriod;
friend class CommandPacketSetNUCFlagState;
friend class CommandPacketStartOnCameraNUC;
friend class CommandPacketConfigureTrigger;
friend class CommandPacketSoftwareTrigger;
friend class CommandPacketSetEventVerbosity;
friend class CommandPacketStreamSubregion;
friend class CommandPacketCancelSubregion;
friend class CommandPacketEraseAllStoredStreams;
friend class CommandPacketListStoredStreams;
friend class CommandPacketEraseStoredStream;
friend class CommandPacketStreamTemperatures;
friend class CommandPacketCancelTemperatures;
friend class CommandPacketStreamPoses;
friend class CommandPacketCancelPoses;
};
/// @brief Command packet to reset the system
class CommandPacketReset : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the RESET opcode.
CommandPacketReset();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketReset(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to start recording
class CommandPacketStartRecording : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the START_RECORDING opcode.
CommandPacketStartRecording();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketStartRecording(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to cancel recording
class CommandPacketStopRecording : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the STOP_RECORDING opcode.
CommandPacketStopRecording();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketStopRecording(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to set the start-up recording state
class CommandPacketSetStartUpRecordingState : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the SET_START_UP_RECORDING_STATE opcode.
/// @param [in] state State to set the start-up recording to (0 = not recording, 1 = recording).
CommandPacketSetStartUpRecordingState(uint32_t state);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketSetStartUpRecordingState(CommandPacket& basePacket);
/// @brief Get the state to set the start-up recording to.
/// @param [out] state State to set the start-up recording to (0 = not recording, 1 = recording).
/// @return OKAY if successful, otherwise an error code.
Status GetState(uint32_t& state) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to start replay.
class CommandPacketStartReplay : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the START_REPLAY opcode.
/// @param [in] ID ID of the stream to replay.
/// @param [in] initialTime Time code of the initial packet to replay.
/// The first packet replayed will have its time code set to this value. Others will be relative to it.
CommandPacketStartReplay(uint32_t ID, Time initialTime);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketStartReplay(CommandPacket& basePacket);
/// @brief Get the ID of the stream to replay.
/// @param [out] ID ID of the stream to replay.
/// @return OKAY if successful, otherwise an error code.
Status GetID(uint32_t& ID) const;
/// @brief Get the time code of the initial packet to replay.
/// @param [out] initialTime Time code of the initial packet to replay.
/// @return OKAY if successful, otherwise an error code.
Status GetInitialTime(Time& initialTime) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to pause replay
class CommandPacketPauseReplay : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the PAUSE_REPLAY opcode.
CommandPacketPauseReplay();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketPauseReplay(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to resume replay
class CommandPacketResumeReplay : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the RESUME_REPLAY opcode.
CommandPacketResumeReplay();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketResumeReplay(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to cancel replay
class CommandPacketStopReplay : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the STOP_REPLAY opcode.
CommandPacketStopReplay();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketStopReplay(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to set the streaming state period.
class CommandPacketSetStreamStatePeriod: public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the SET_STREAM_STATE_PERIOD opcode.
/// @param [in] interval Interval to stream at in seconds.
CommandPacketSetStreamStatePeriod(float interval);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketSetStreamStatePeriod(CommandPacket& basePacket);
/// @brief Get the interval to stream at.
/// @param [out] interval Interval to stream at in seconds.
/// @return OKAY if successful, otherwise an error code.
Status GetInterval(float& interval) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to set the NUC flag state.
class CommandPacketSetNUCFlagState : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the SET_NUC_FLAG_STATE opcode.
/// @param [in] ID ID of the camera to set the NUC flag for.
/// @param [in] state State to set the NUC flag to (0 = off, 1 = on).
CommandPacketSetNUCFlagState(uint32_t ID, uint32_t state);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketSetNUCFlagState(CommandPacket& basePacket);
/// @brief Get the ID of the camera to set the NUC flag on.
/// @param [out] ID ID of the camera to set the NUC flag on.
/// @return OKAY if successful, otherwise an error code.
Status GetID(uint32_t& ID) const;
/// @brief Get the state to set the NUC flag to.
/// @param [out] state State to set the NUC flag to (0 = off, 1 = on).
/// @return OKAY if successful, otherwise an error code.
Status GetState(uint32_t& state) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to start on-camera NUC.
class CommandPacketStartOnCameraNUC : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the START_ON_CAMERA_NUC opcode.
/// @param [in] ID ID of the camera to start the NUC on.
CommandPacketStartOnCameraNUC(uint32_t ID);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketStartOnCameraNUC(CommandPacket& basePacket);
/// @brief Get the ID of the camera to start the NUC on.
/// @param [out] ID ID of the camera to start the NUC on.
/// @return OKAY if successful, otherwise an error code.
Status GetID(uint32_t& ID) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to configure a trigger.
class CommandPacketConfigureTrigger : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the CONFIGURE_TRIGGER opcode.
/// @param [in] config Information about the trigger.
CommandPacketConfigureTrigger(TriggerInfo config);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketConfigureTrigger(CommandPacket& basePacket);
/// @brief Get the configuration for the trigger.
/// @param [out] config Configuration for the trigger.
/// @return OKAY if successful, otherwise an error code.
Status GetConfiguration(TriggerInfo &config) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to send a software trigger.
class CommandPacketSoftwareTrigger : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the SOFTWARE_TRIGGER opcode.
/// @param [in] ID ID of the trigger.
/// @param [in] initialTime Time code of the trigger.
/// The first packet replayed will have its time code set to this value. Others will be relative to it.
CommandPacketSoftwareTrigger(uint8_t ID, Time initialTime);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketSoftwareTrigger(CommandPacket& basePacket);
/// @brief Get the ID of the trigger.
/// @param [out] ID ID of the trigger.
/// @return OKAY if successful, otherwise an error code.
Status GetID(uint8_t& ID) const;
/// @brief Get the time code of the trigger.
/// @param [out] initialTime Time code of the trigger.
/// @return OKAY if successful, otherwise an error code.
Status GetInitialTime(Time& initialTime) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to set the verbosity of event streaming.
class CommandPacketSetEventVerbosity : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the SET_EVENT_VERBOSITY opcode.
/// @param [in] verbosity Verbosity of the events to stream.
CommandPacketSetEventVerbosity(uint8_t verbosity);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketSetEventVerbosity(CommandPacket& basePacket);
/// @brief Get the verbosity of the events to stream.
/// @param [out] verbosity Verbosity of the events to stream.
/// @return OKAY if successful, otherwise an error code.
Status GetVerbosity(uint8_t& verbosity) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Structure describing a subregion.
struct SubregionDescription {
uint32_t cameraID; ///< Camera ID the region is from
uint32_t skipFrames; ///< Number of frames to skip between frames in the subregion
uint32_t startTimeSeconds; ///< Time of the first frame to be streamed
uint32_t startTimeMicroseconds; ///< Time of the first frame to be streamed
uint16_t left; ///< Left side of the subregion
uint16_t top; ///< Top side of the subregion
uint16_t right; ///< Right side of the subregion
uint16_t bottom; ///< Bottom side of the subregion
/// @brief Equality operator.
bool operator ==(const SubregionDescription& other) const {
return cameraID == other.cameraID &&
skipFrames == other.skipFrames &&
startTimeSeconds == other.startTimeSeconds &&
startTimeMicroseconds == other.startTimeMicroseconds &&
left == other.left &&
top == other.top &&
right == other.right &&
bottom == other.bottom;
};
/// @brief Inequality operator.
bool operator !=(const SubregionDescription& other) const {
return !(*this == other);
};
};
/// @brief Command packet to stream subregion.
class CommandPacketStreamSubregion : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the STREAM_SUBREGION opcode.
/// @param [in] endpoint Endpoint to stream to.
/// @param [in] region Subregion to stream.
CommandPacketStreamSubregion(StreamEndpoint endpoint, SubregionDescription const ®ion);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketStreamSubregion(CommandPacket& basePacket);
/// @brief Get the endpoint.
/// @param [out] endpoint Endpoint to stream to.
/// @return OKAY if successful, otherwise an error code.
Status GetEndpoint(StreamEndpoint& endpoint) const;
/// @brief Get the subregion description.
/// @param [out] region Region description.
/// @return OKAY if successful, otherwise an error code.
Status GetRegionDescription(SubregionDescription ®ion) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to cancel streaming subregion.
class CommandPacketCancelSubregion : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the CANCEL_SUBREGION opcode.
/// @param [in] camera Camera to stop streaming to.
/// @param [in] endpoint Endpoint to stop streaming to.
CommandPacketCancelSubregion(uint32_t camera, StreamEndpoint endpoint);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketCancelSubregion(CommandPacket& basePacket);
/// @brief Get the camera to stop streaming to.
/// @param [out] camera Camera to stop streaming to.
/// @return OKAY if successful, otherwise an error code.
Status GetCamera(uint32_t& camera) const;
/// @brief Get the endpoint.
/// @param [out] endpoint Endpoint to stop streaming to.
/// @return OKAY if successful, otherwise an error code.
Status GetEndpoint(StreamEndpoint& endpoint) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to erase all stored streams.
class CommandPacketEraseAllStoredStreams : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the ERASE_ALL_STORED_STREAMS opcode.
CommandPacketEraseAllStoredStreams();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketEraseAllStoredStreams(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to send the list of stored streams (there is no corresponding cancel).
class CommandPacketListStoredStreams : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the LIST_STORED_STREAMS opcode.
CommandPacketListStoredStreams();
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketListStoredStreams(CommandPacket& basePacket);
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to start replay.
class CommandPacketEraseStoredStream : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the ERASE_STORED_STREAM opcode.
/// @param [in] ID ID of the stream to erase.
CommandPacketEraseStoredStream(uint32_t ID);
/// @brief Type-cast a base CommandPacket, re-using its buffer.
/// @param [in] basePacket The base packet to convert from.
CommandPacketEraseStoredStream(CommandPacket& basePacket);
/// @brief Get the ID of the stream to eraase.
/// @param [out] ID ID of the stream to erase.
/// @return OKAY if successful, otherwise an error code.
Status GetID(uint32_t& ID) const;
/// @brief Test function.
/// @return Empty string if successful, otherwise descriptive error message.
static std::string Test();
};
/// @brief Command packet to start streaming temperatures.
class CommandPacketStreamTemperatures : public CommandPacket {
public:
/// @brief Construct a brand-new command buffer with the STREAM_TEMPERATURES opcode.